O MaxCompute utiliza a versão Python 2.7. Este tópico descreve como escrever uma função definida pelo usuário (UDF) em Python 2.
Estrutura do código da UDF
Use o MaxCompute Studio para escrever o código da UDF em Python 2. O código pode conter os seguintes elementos:
-
Declaração de codificação: opcional.
O formato da declaração é
#coding:utf-8ou# -*- coding: utf-8 -*-. Ambos os formatos são equivalentes. Se o código da UDF em Python 2 contiver caracteres chineses, a execução retornará um erro. Para resolver esse problema, adicione uma declaração de codificação no cabeçalho do código. -
Importação de módulo: obrigatória.
O código da UDF deve incluir
from odps.udf import annotatepara importar a assinatura da função. Isso permite que o MaxCompute identifique a assinatura definida no código. Para referenciar arquivos ou tabelas no código da UDF, incluafrom odps.distcache import get_cache_fileoufrom odps.distcache import get_cache_table. -
Assinatura da função: obrigatória.
A assinatura da função segue o formato
@annotate(<signature>). O parâmetrosignaturedefine os tipos de dados dos parâmetros de entrada e do valor de retorno da UDF. Para mais informações sobre assinaturas de função, consulte Function signatures and data types. -
Classe Python personalizada: obrigatória.
A classe Python personalizada é a unidade organizacional do código da UDF. Essa classe define as variáveis e os métodos necessários para atender aos requisitos de negócios. No código da UDF, também é possível referenciar bibliotecas de terceiros instaladas no MaxCompute, além de arquivos ou tabelas. Para mais detalhes, consulte Third-party libraries ou Reference resources.
-
Método
evaluate: obrigatório.O método evaluate reside na classe Python personalizada. O método
evaluatedefine os parâmetros de entrada e o valor de retorno da UDF. Cada classe Python pode conter apenas um métodoevaluate.
Código de exemplo:
#coding:utf-8
# Import the function signature.
from odps.udf import annotate
# The function signature.
@annotate("bigint,bigint->bigint")
# The custom Python class.
class MyPlus(object):
# The evaluate method.
def evaluate(self, arg0, arg1):
if None in (arg0, arg1):
return None
return arg0 + arg1
Limites
O MaxCompute permite escrever UDFs Python 2 na versão 2.7 e executar o código em um ambiente sandbox. Nesse ambiente, as seguintes operações são proibidas:
Ler e gravar dados em arquivos locais.
Iniciar subprocessos.
Iniciar threads.
Ativar comunicação por socket.
Usar outros sistemas para chamar UDFs Python 2.
Devido a esses limites, escreva o código enviado com bibliotecas padrão do Python. Se módulos ou módulos de extensão C das bibliotecas padrão envolverem as operações mencionadas acima, não será possível utilizá-los. Observe os seguintes pontos sobre os módulos das bibliotecas padrão do Python:
Todos os módulos implementados com base nas bibliotecas padrão do Python que não dependem de módulos de extensão estão disponíveis.
-
Os seguintes módulos de extensão C estão disponíveis:
array e audioop
binascii e bisect
cmath, _codecs_cn, _codecs_hk, _codecs_iso2022, _codecs_jp, _codecs_kr, _codecs_tw, _collections e cStringIO
datetime
_functools e future_builtins
_heapq e _hashlib
itertools
_json
_locale e _lsprof
math, _md5 e _multibytecodec
operator
_random
_sha256, _sha512, _sha, _struct e strop
time
unicodedata
_weakref
cPickle
Ao executar o código da UDF em um ambiente sandbox, o tamanho máximo de dados graváveis na saída padrão (sys.stdout) ou na saída de erro padrão (
sys.stderr) é de 20 KB. Se o tamanho exceder 20 KB, o sistema ignorará os caracteres extras.
Bibliotecas de terceiros
Bibliotecas de terceiros, como NumPy, estão instaladas no ambiente Python 2 do MaxCompute como complemento às bibliotecas padrão.
O uso de bibliotecas de terceiros está sujeito a alguns limites. Por exemplo, ao usar uma biblioteca de terceiros, não é permitido acessar dados locais e apenas recursos limitados de I/O de rede podem ser utilizados. As APIs relacionadas nessas bibliotecas ficam desativadas.
Assinaturas de função e tipos de dados
Formato das assinaturas de função:
@annotate(<signature>)
O parâmetro signature é uma string que especifica os tipos de dados dos parâmetros de entrada e do valor de retorno. Ao executar uma UDF, os tipos de dados dos parâmetros de entrada e do valor de retorno devem corresponder aos tipos especificados na assinatura da função. A análise semântica verifica a consistência dos tipos de dados. Se houver inconsistência, o sistema retornará um erro. Formato de uma assinatura:
'arg_type_list -> type'
Descrição dos parâmetros:
-
arg_type_list: especifica os tipos de dados dos parâmetros de entrada. Se houver múltiplos parâmetros de entrada, separe seus tipos de dados por vírgulas (,). Os seguintes tipos de dados são suportados: BIGINT, STRING, DOUBLE, BOOLEAN, DATETIME, DECIMAL, FLOAT, BINARY, DATE, DECIMAL(precision,scale), CHAR e VARCHAR. Tipos de dados complexos, como ARRAY, MAP e STRUCT, bem como tipos complexos aninhados, também são suportados.arg_type_listpode ser representado por um asterisco (*) ou deixado vazio ('').Se
arg_type_listfor representado por um asterisco (*), um número variável de parâmetros de entrada será permitido.Se
arg_type_listfor deixado vazio (''), nenhum parâmetro de entrada será usado.
type: especifica o tipo de dados do valor de retorno. Uma UDF retorna apenas uma coluna de valores. Os seguintes tipos de dados são suportados: BIGINT, STRING, DOUBLE, BOOLEAN, DATETIME, DECIMAL, FLOAT, BINARY, DATE e DECIMAL(precision,scale). Tipos de dados complexos, como ARRAY, MAP e STRUCT, bem como tipos complexos aninhados, também são suportados.
Ao escrever o código da UDF, selecione um tipo de dados com base na edição de tipos de dados do MaxCompute utilizada pelo seu projeto. Para mais informações sobre as edições de tipos de dados do MaxCompute e os tipos suportados em cada edição, consulte Data type editions.
A tabela a seguir fornece exemplos de assinaturas de função válidas.
|
Assinatura da função |
Descrição |
|
|
Os tipos de dados dos parâmetros de entrada são BIGINT e DOUBLE, e o tipo de dados do valor de retorno é STRING. |
|
|
Um número variável de parâmetros de entrada é utilizado e o tipo de dados do valor de retorno é STRING. |
|
|
Nenhum parâmetro de entrada é utilizado e o tipo de dados do valor de retorno é DOUBLE. |
|
|
O tipo de dados dos parâmetros de entrada é ARRAY<BIGINT> e o tipo de dados do valor de retorno é STRUCT<x:STRING, y:INT>. |
|
|
Nenhum parâmetro de entrada é utilizado e o tipo de dados do valor de retorno é MAP<BIGINT, STRING>. |
A tabela a seguir descreve os mapeamentos entre os tipos de dados suportados no MaxCompute SQL e os tipos de dados do Python 2. Escreva as UDFs Python com base nesses mapeamentos para garantir a consistência dos tipos de dados.
|
Tipo de dados do MaxCompute SQL |
Tipo de dados do Python 2 |
|
BIGINT |
INT |
|
STRING |
STR |
|
DOUBLE |
FLOAT |
|
BOOLEAN |
BOOL |
|
DATETIME |
INT |
|
FLOAT |
FLOAT |
|
CHAR |
STR |
|
VARCHAR |
STR |
|
BINARY |
BYTEARRAY |
|
DATE |
INT |
|
DECIMAL |
DECIMAL.DECIMAL |
|
ARRAY |
LIST |
|
MAP |
DICT |
|
STRUCT |
COLLECTIONS.NAMEDTUPLE |
O tipo DATETIME suportado no MaxCompute SQL é mapeado para o tipo de dados INT do Python. Um valor do tipo INT segue o formato UNIX, que corresponde ao número de milissegundos decorridos desde 00:00:00 de quinta-feira, 1º de janeiro de 1970. Processe dados do tipo DATETIME usando o módulo DATETIME nas bibliotecas padrão do Python.
O parâmetro
silentfoi adicionado aodps.udf.int(value). Se o parâmetrosilentestiver definido como True e o tipo de dados devaluenão puder ser convertido para o tipo INT, None será retornado sem gerar erro.NULL no MaxCompute SQL é mapeado para None no Python 2.
Referenciar recursos
Referencie arquivos ou tabelas no código da UDF Python 2 usando o módulo odps.distcache.
-
odps.distcache.get_cache_file(resource_name): retorna o conteúdo de um arquivo especificado.-
resource_nameé uma string que especifica o nome de um arquivo existente no seu projeto MaxCompute. Se o nome do arquivo for inválido ou se o arquivo não existir, um erro será retornado.NotaPara referenciar um arquivo no código da UDF, declare-o ao criar a UDF. Caso contrário, um erro será retornado ao chamar a UDF.
O valor de retorno é um objeto semelhante a um arquivo. Se esse objeto não for mais utilizado, chame o método
closepara liberar o arquivo aberto.
O código a seguir mostra como referenciar um arquivo.
from odps.udf import annotate from odps.distcache import get_cache_file @annotate('bigint->string') class DistCacheExample(object): def __init__(self): cache_file = get_cache_file('test_distcache.txt') kv = {} for line in cache_file: line = line.strip() if not line: continue k, v = line.split() kv[int(k)] = v cache_file.close() self.kv = kv def evaluate(self, arg): return self.kv.get(arg) -
-
odps.distcache.get_cache_table(resource_name): retorna o conteúdo de uma tabela especificada.resource_nameé uma string que especifica o nome de uma tabela existente no seu projeto MaxCompute. Se o nome da tabela for inválido ou se a tabela não existir, um erro será retornado.O valor de retorno é do tipo de dados GENERATOR. O chamador percorre a tabela para obter seu conteúdo. Um registro do tipo ARRAY é obtido a cada iteração.
O código a seguir mostra como referenciar uma tabela.
from odps.udf import annotate from odps.distcache import get_cache_table @annotate('->string') class DistCacheTableExample(object): def __init__(self): self.records = list(get_cache_table('udf_test')) self.counter = 0 self.ln = len(self.records) def evaluate(self): if self.counter > self.ln - 1: return None ret = self.records[self.counter] self.counter += 1 return str(ret)
Processo de desenvolvimento
Ao desenvolver uma UDF, faça os preparativos, escreva o código da UDF, envie o programa Python, crie a UDF, depure-a e chame-a. O MaxCompute permite usar várias ferramentas para desenvolver uma UDF, como MaxCompute Studio, DataWorks e o cliente MaxCompute (odpscmd).
O processo de uso de várias ferramentas para desenvolver UDFs em Python 2 é igual ao processo de desenvolvimento de UDFs em Python 3. Para mais informações sobre o processo de desenvolvimento e exemplos de como desenvolver uma UDF em Python, consulte Development process.
Para mais informações sobre como usar o MaxCompute Studio para desenvolver e chamar uma UDF em Python 2, consulte Develop a Python UDF.
Notas de uso
Após desenvolver uma UDF Python 2, use o MaxCompute SQL para chamá-la. Chame uma UDF Python 2 usando um dos seguintes métodos:
Usar uma UDF em um projeto MaxCompute: este método é semelhante ao uso de built-in functions. Utilize uma função definida pelo usuário da mesma forma que uma função integrada.
Usar uma UDF entre projetos: utilize uma UDF do Projeto B no Projeto A. A instrução a seguir mostra um exemplo:
select B:udf_in_other_project(arg0, arg1) as res from table_t;. Para mais informações sobre compartilhamento entre projetos, consulte Cross-project resource access based on packages.