Este tópico descreve as perguntas frequentes (FAQ) sobre funções definidas pelo usuário (UDFs) do MaxCompute escritas em Python.
Problemas de classe ou recurso
Esta seção aborda problemas comuns de classe e recurso que ocorrem ao chamar uma UDF do MaxCompute.
-
Sintoma 1: A mensagem de erro function 'xxx' cannot be resolved é retornada.
-
Causas:
Causa 1: A UDF do MaxCompute está sendo chamada no projeto incorreto. A UDF não existe no projeto atual do MaxCompute. Por exemplo, a UDF foi registrada em um projeto de desenvolvimento, mas a chamada ocorre a partir de um projeto de produção.
Causa 2: A classe ou o recurso da UDF do MaxCompute está incorreto.
Causa 3: O tipo de recurso do qual a UDF do MaxCompute depende está incorreto. Por exemplo, um arquivo PY tem o tipo de recurso PY, mas o método
get_cache_fileno código da UDF exige o tipo FILE.Causa 4: O recurso do qual a UDF do MaxCompute depende está desatualizado. Pode ocorrer um atraso ao carregar um recurso do DataWorks para o MaxCompute, o que significa que o recurso pode não estar na versão mais recente.
Causa 5: A versão do ambiente Python está incorreta. Por padrão, o MaxCompute executa jobs em um ambiente Python 2. Ocorre um erro se o código Python contiver caracteres não ASCII.
-
Soluções:
Solução para a Causa 1: No projeto onde o erro ocorreu, execute o comando
list functions;no MaxCompute client para verifique se a Função Definida pelo Usuário (UDF) do MaxCompute existe.-
Solução para a Causa 2: No MaxCompute client, execute o comando
desc function <function_name>;e verifique se os campos Class e Resources na saída estão corretos.Se estiverem incorretos, execute o comando
create function <function_name> as <'package_to_class'> using <'resource_list'>;para registrar a função novamente. Nesse comando, package_to_class corresponde a nome_do_script_python.nome_da_classe e resource_list inclui todos os recursos de arquivo, tabela e archive, ou pacotes de terceiros necessários para referência no MaxCompute.Para obter mais informações, consulte Register a function.
-
Solução para a Causa 3: No MaxCompute client, execute o comando
desc resource <resource_name>;e verifique se o campo Type na saída está correto. Se o tipo de recurso estiver incorreto, execute o comandoadd <file_type> <file_name>;para adicionar o recurso novamente.Se o recurso for referenciado usando
get_cache_fileno código da UDF, trata-se de um recurso de arquivo. O tipo de recurso deve ser FILE.Se o recurso for referenciado usando
get_cache_tableno código da UDF, trata-se de um recurso de tabela. O tipo de recurso deve ser TABLE.Se o recurso for referenciado usando
get_cache_archiveno código da UDF, trata-se de um recurso de archive. O tipo de recurso deve ser ARCHIVE.
Para obter mais informações, consulte Add a resource.
Solução para a Causa 4: Execute o comando
desc resource <resource_name>;no MaxCompute client e verifique o campo LastModifiedTime na saída para confirmar a última data de modificação.Solução para a Causa 5: Adicione a declaração de codificação
#coding:utf-8ou# -*- coding: utf-8 -*-no início do código Python. Alternativamente, adicione a instruçãoset odps.sql.python.version=cp37;antes da instrução SQL que chama a UDF. Em seguida, envie-as juntas para executar o job em um ambiente Python 3.
-
-
Sintoma 2: Ao usar
get_cache_archive('xxx.zip')em uma UDF do MaxCompute, uma das seguintes mensagens de erro é retornada: IOError: Download resource: xxx.zip failed, odps.distcache.DistributedCacheError ou fuxi job failed: Download resource failed: xxx.zip.-
Causas:
Causa 1: O recurso de archive não existe. O recurso de archive não foi especificado durante o registro da UDF do MaxCompute.
Causa 2: O tipo de recurso do archive está incorreto. Não é ARCHIVE.
Causa 3: O nome ou a extensão do recurso de archive é inconsistente com o arquivo real. Por exemplo, o recurso de archive chama-se xxx.zip, mas o arquivo enviado é xxx.tar.gz. O sistema tenta descompactar o arquivo no formato ZIP, o que causa falha na descompactação.
Causa 4: Duas UDFs no mesmo job dependem de recursos com o mesmo nome, mas em projetos diferentes.
-
Soluções:
-
Solução para a Causa 1: Execute o comando
desc function <function_name>;no MaxCompute client para verificar se o campo Resources na saída contém o pacote de recurso compactado especificado na mensagem de erro.Se não estiver incluído, execute o comando
create function <function_name> as <'package_to_class'> using <'resource_list'>;para registrar a função novamente. Adicione o recurso de archive ausente à resource_list.Para obter mais informações, consulte Register a function.
-
Solução para a Causa 2: Execute o comando
desc resource <resource_name>;no MaxCompute client para verificar se o campo Type na saída é ARCHIVE.Se o tipo não for ARCHIVE, execute o comando
add archive <file_name>;para carregar o recurso novamente.Para obter mais informações, consulte Add a resource.
-
Solução para a Causa 3: No MaxCompute client, execute o comando
desc function <function_name>;para verificar se o nome e a extensão do recurso de pacote compactado na seção Resources da saída correspondem ao nome e à extensão reais do arquivo.Se forem inconsistentes, execute o comando
add archive <file_name>;para carregar o recurso novamente. O file_name deve ser idêntico ao nome e à extensão do recurso de archive real. Solução para a Causa 4: Verifique todas as UDFs das quais o job depende, incluindo UDFs em views. Examine o projeto e o nome de cada UDF e seu recurso correspondente. Se existirem recursos com o mesmo nome em projetos diferentes, altere o nome da UDF dependente ou do recurso.
-
-
-
Sintoma 3: Ao usar
get_cache_table(table_name)em uma UDF do MaxCompute, a mensagem de erro odps.distcache.DistributedCacheError: Table resource "xxx_table_name" not found é retornada.-
Causas:
Causa 1: O recurso de tabela não existe. O recurso de tabela não foi especificado durante o registro da UDF do MaxCompute.
Causa 2: O tipo de recurso da tabela está incorreto. Não é TABLE.
-
Soluções:
-
Solução para a Causa 1: No the MaxCompute client, execute o comando
desc function <function_name>;e verifique se o campo Resources na saída contém o recurso de tabela mencionado na mensagem de erro.Se não estiver incluído, execute o comando
create function <function_name> as <'package_to_class'> using <'resource_list'>;para registrar a função novamente. Adicione o recurso de tabela ausente à resource_list.Para obter mais informações, consulte Register a function.
-
Solução para a Causa 2: No MaxCompute client, execute o comando
desc resource <resource_name>;e verifique se o campo Type na saída é TABLE.Se o tipo não for TABLE, execute o comando
add table <table_name>;para carregar o recurso de tabela novamente.Para obter mais informações, consulte Add a resource.
-
-
-
Sintoma 4: Quando uma UDF do MaxCompute referencia um pacote de terceiros, a mensagem de erro ImportError: No module named 'xxx' é retornada.
-
Causa
Causa 1: O
resource typedopackagede terceiros está incorreto. Oresource typedeve ser ARCHIVE.Causa 2: O
packagede terceiros não foi especificado quando a UDF doMaxComputefoi registrada.Causa 3: O
pathpara opackagede terceiros não foi adicionado ao código da UDF doMaxCompute.Causa 4: O
packagede terceiros é umpackageWHEEL, mas ofiletem uma extensão incorreta ou não corresponde à versão doenvironmentPython.Causa 5: O
packagede terceiros não é umpackageWHEEL nem umpackagePython puro, mas contém umfilesetup.py.Causa 6: O nome do
filePython da UDF doMaxComputeentra em conflito com o nome do módulo de terceiros que você desejareference. Por exemplo, se ofilePython da UDF for A.py, o sistema importa A.py pordefaultem vez do módulo dopackagede terceiros quando você executaimport A.
-
Soluções:
-
Solução para a Causa 1: No MaxCompute client, execute o comando
desc resource <resource_name>;e verifique se o parâmetro Type na saída é ARCHIVE.Se o tipo não for ARCHIVE, execute o comando
add archive <file_name>;para carregar o recurso novamente.Para obter mais informações, consulte Add a resource.
-
Solução para a Causa 2: Use o MaxCompute client para executar o comando
desc function <function_name>;e verifique se o parâmetro Resources na saída inclui pacotes de terceiros.Se não estiverem incluídos, execute o comando
create function <function_name> as <'package_to_class'> using <'resource_list'>;para registrar a função novamente. Adicione o pacote de terceiros à resource_list.Para obter mais informações, consulte Register a function.
-
Solução para a Causa 3: Verifique se o caminho para o pacote de terceiros foi adicionado ao código da função definida pelo usuário (UDF). Especificamente, confirme se o código inclui
sys.path.insert(0, 'work/path_to_third_party_package'). Por exemplo, suponha que o nome do módulo seja A e o arquivo Python correspondente seja A.py. Os exemplos a seguir descrevem como determinar o caminho do pacote de recurso e adicioná-lo ao seu código:Se o arquivo Python estiver na pasta resource_dir e você compactar diretamente a pasta resource_dir em resource-of-A.zip, o caminho em
sys.path.insertseráwork/resource-of-A.zip/resource_dir/.Se o arquivo Python estiver na pasta resource_dir e você compactar todos os arquivos dentro da pasta resource_dir em resource-of-A.zip, o caminho em
sys.path.insertseráwork/resource-of-A.zip/.Se o arquivo Python estiver na pasta resource_dir/path1/path2 e você compactar todos os arquivos dentro da pasta resource_dir em resource-of-A.zip, o caminho em
sys.path.insertseráwork/resource-of-A.zip/path1/path2/.
NotaPor padrão, os recursos ARCHIVE são colocados no diretório
./work/, que é relativo ao caminho de execução da UDF. Solução para a Causa 4: Os arquivos WHEEL são diferentes para ambientes Python 2 e Python 3. Para Python 2, o nome do arquivo WHEEL deve conter
cp27-cp27m-manylinux1_x86_64. Para Python 3, o nome do arquivo WHEEL deve contercp37-cp37m-manylinux1_x86_64. Baixe o arquivo WHEEL apropriado. Você pode alterar diretamente a extensão do arquivo WHEEL baixado para .zip. Não é necessário compactar o arquivo WHEEL em outro arquivo ZIP.Solução para a Causa 5: Primeiro, compile o arquivo setup.py para gerar um pacote WHEEL em um ambiente compatível com o MaxCompute. Em seguida, carregue o recurso e registre a função. Para obter mais informações sobre como compilar um pacote de terceiros, consulte Use a third-party package that requires compilation.
Solução para a Causa 6: Renomeie o arquivo Python da UDF do MaxCompute.
-
-
-
Sintoma 5: Quando uma UDF do MaxCompute referencia uma biblioteca padrão do Python 3, a mensagem de erro ImportError: No module named enum é relatada.
Causa: O Python 3 não está ativado para o projeto do MaxCompute. Por padrão, a UDF do MaxCompute é executada em um ambiente Python 2, que não reconhece bibliotecas padrão do Python 3.
Solução: Adicione a instrução
set odps.sql.python.version=cp37;antes da instrução SQL que chama a UDF e envie-as juntas.
-
Sintoma 6: A mensagem de erro ModuleNotFoundError: No module named 'six' é retornada.
Causa: O caminho para o pacote de terceiros não foi adicionado ao
sys.path. Isso impede que a UDF Python importe o pacote.Solução: Para obter mais informações, consulte Executar Scipy em uma UDF do MaxCompute. Altere
include_package_path('six.zip')parasys.path.insert(0, 'work/six.zip').
-
Sintoma 7: A mensagem de erro failed to get Udf info from xxx.py é relatada.
Causa: A classe base foi importada com sintaxe incorreta na função com valor de tabela definida pelo usuário (UDTF) ou na função de agregação definida pelo usuário (UDAF). Por exemplo,
import odps.udf.BaseUDTFouimport odps.udf.BaseUDAF.Solução: Altere a instrução de importação para
from odps.udf import BaseUDTFoufrom odps.udf import BaseUDAF.
Problemas de desempenho
Sintoma: A mensagem de erro kInstanceMonitorTimeout é retornada.
Causa: O tempo de processamento da UDF excede o limite de timeout. Por padrão, um lote de registros (geralmente 1.024) deve ser processado em até 1.800 segundos. Esse limite aplica-se ao processamento de um único lote, não ao tempo total de execução do worker. O SQL normalmente processa dados a mais de 10.000 registros por segundo. O limite evita loops infinitos em UDFs que causariam uso prolongado da CPU.
-
Solução:
-
Adicione logs ao código da UDF do MaxCompute para verificar a existência de loops infinitos. Também é possível imprimir informações de tempo nos logs para verificar se o tempo de processamento de um único registro atende às expectativas. Adicione as seguintes informações de impressão de log ao seu código. Após a execução bem-sucedida do job, visualize as informações de log em StdOut no Logview.
-
Ambiente Python 2
sys.stdout.write('your log') sys.stdout.flush() -
Ambiente Python 3
print('your log', flush=True)
-
-
Se a computação real for extensa e a UDF tiver previsão de execução longa, ajuste os seguintes parâmetros para evitar erros de timeout.
Parâmetro
Descrição
set odps.function.timeout=xxx;Ajusta o período de timeout de execução da UDF. O valor padrão é 1800s. Aumente esse valor conforme necessário. O valor deve estar no intervalo de 1s a 3600s.
set odps.sql.executionengine.batch.rowcount=xxx;Define o número de linhas de dados que o MaxCompute processa por vez. O valor padrão é 1024. Diminua esse valor conforme necessário.
-
Problemas de rede
Sintoma: Ocorre um erro ao chamar uma UDF do MaxCompute para acessar a internet.
Causa: As UDFs do MaxCompute não suportam acesso à internet.
Solução: Preencha e envie o formulário de Solicitação de Conexão de Rede com base nas necessidades do seu negócio. A equipe de suporte técnico do MaxCompute entrará em contato prontamente para ative o acesso à rede. Para obter instruções sobre como preencher o formulário, consulte Network access process.
Problemas de sandbox
Sintoma: A mensagem de erro RuntimeError: xxx has been blocked by sandbox é retornada.
Causa: Algumas chamadas de função na UDF Python foram bloqueadas pela sandbox.
-
Solução:
Antes da instrução SQL que chama a UDF Python, adicione a configuração
set odps.isolation.session.enable=true;. Em seguida, envie-as juntas.Se você usar uma UDF Python 3, a configuração
set odps.isolation.session.enable=true;já estará ativada por padrão.
Problemas de codificação
Esta seção descreve problemas comuns de codificação que ocorrem ao chamar uma UDF do MaxCompute.
-
Sintoma 1: A mensagem de erro SyntaxError: Non-ASCII character '\xe8' in file xxx. on line yyy é retornada.
Causa: O arquivo Python da UDF do MaxCompute contém caracteres não ASCII e está sendo executado em um ambiente Python 2.
-
Solução:
Adicione a instrução
set odps.sql.python.version=cp37;antes da instrução SQL que chama a UDF. Em seguida, envie-as juntas para executar o job em um ambiente Python 3.-
Altere a codificação padrão do interpretador Python 2 para UTF-8. Para isso, adicione as seguintes instruções no início do arquivo Python.
import sys reload(sys) sys.setdefaultencoding('utf-8')
-
Sintoma 2: Ao chamar uma UDF Python 2, a mensagem de erro UnicodeEncodeError: 'ascii' code can't encode characters in position x-y: ordinal not in range(128) é retornada.
Causa: O tipo de valor de retorno na assinatura da função é STRING, mas a UDF do MaxCompute retorna um objeto Python do tipo UNICODE. Suponha que o objeto se chame ret. Por padrão, o MaxCompute tenta converter o valor de retorno ret para o tipo STR usando o formato de codificação ASCII e retorna
str(ret). Se ret contiver apenas caracteres ASCII, a conversão para o tipo STR será bem-sucedida. No entanto, se ret contiver caracteres não ASCII, a conversão falhará e um erro será retornado.-
Solução: Adicione a seguinte instrução ao método
evaluateno código Python.return ret.encode('utf-8')
-
Sintoma 3: Ao chamar uma UDF Python 3, a mensagem de erro UnicodeDecodeError: 'utf-8' codec can't decode byte xxx in position xxx: invalid continuation byte é retornada.
Causa: O tipo de parâmetro de entrada na assinatura da função é STRING. No entanto, a string de entrada não pode ser decodificada para um objeto Python do tipo STR usando UTF-8 quando você chama a UDF Python 3.
-
Soluções:
-
Evite gravar strings com codificação não UTF-8 em tabelas do MaxCompute.
Por exemplo, uma UDF Python 2 retorna um objeto Python do tipo STR codificado em GBK. Esse objeto pode ser gravado em uma tabela do MaxCompute, mas não pode ser lido por uma UDF Python 3. Converta os dados para codificação UTF-8 antes que a UDF Python 2 os retorne. Por exemplo, retorne
ret.decode('gbk').encode('utf-8'). -
Na instrução SQL, use a função interna
is_encodingpara filtrar previamente dados com codificação não UTF-8. O código a seguir fornece um exemplo.select py_udf(input_col) from example_table where is_encoding(input_col, 'utf-8', 'utf-8') = true; -
Altere o tipo de parâmetro de entrada na assinatura da função no código Python para BINARY. Na instrução SQL, converta a coluna do tipo STRING para o tipo BINARY e use-a como parâmetro de entrada para a UDF Python 3. O código a seguir fornece um exemplo.
select py_udf(cast(input_col as binary)) from example_table;
-
Problemas de assinatura de função
Esta seção descreve problemas comuns de assinatura de função que ocorrem ao chamar uma UDF do MaxCompute.
-
Sintoma 1: A mensagem de erro resolve annotation of class xxx for UDTF/UDF/UDAF yyy contains invalid content '<EOF>' é retornada.
Causa: O parâmetro de entrada ou saída da UDF do MaxCompute é um tipo de dados complexo, mas a assinatura da função é inválida.
Solução: Modifique o tipo de dados complexo na assinatura da função para garantir que a assinatura seja válida. Para obter mais informações sobre assinaturas de função, consulte Function signatures and data types.
-
Sintoma 2: A mensagem de erro TypeError: expected <class 'xxx'> but <class 'yyy'> found, value:zzz é retornada.
Causa: O tipo de valor de retorno especificado na assinatura da função é inconsistente com o tipo de dados que o código da UDF do MaxCompute realmente retorna.
Solução: Confirme o resultado de retorno esperado. Modifique a assinatura da função ou o código da UDF do MaxCompute para garantir que os tipos de dados sejam consistentes.
-
Sintoma 3: A mensagem de erro Semantic analysis exception - evaluate function in class xxx.yyy for user defined function zz does not match annotation -> é retornada.
Causa: O número de parâmetros de entrada especificado na assinatura da função é inconsistente com o número de parâmetros de entrada no método correspondente no código da UDF do MaxCompute.
Solução: Confirme o número real de parâmetros de entrada. Modifique a assinatura da função ou o código da UDF do MaxCompute para garantir que o número de parâmetros de entrada seja consistente.
Problemas com pacotes de terceiros
Sintoma: A mensagem de erro GLIBCXX_x.x.x not found é retornada.
Causa: A versão GLIBCXX da qual o arquivo de biblioteca vinculada .so depende é posterior à versão suportada pelo MaxCompute. O mesmo se aplica a GLIBC e CXXABI.
-
Solução: Use um pacote WHEEL compatível ou recompile o arquivo de biblioteca vinculada .so em um ambiente compatível. A lista a seguir mostra as versões mais recentes de dependências suportadas para arquivos executáveis binários ou arquivos de biblioteca vinculada .so no MaxCompute.
GLIBC <= 2.17 CXXABI <= 1.3.8 GLIBCXX <= 3.4.19 GCC <= 4.2.0
Problemas relacionados a UDTF
Sintoma: A mensagem de erro Semantic analysis exception - expect 2 aliases but have 0 é retornada.
Causa: Os nomes das colunas de saída não foram especificados no código da UDTF Python.
-
Solução: Especifique os nomes das colunas na cláusula
asda instrução SELECT que chama a UDTF Python. O comando a seguir fornece um exemplo.select my_udtf(col0, col1) as (ret_col0, ret_col1, ret_col2) from tmp1;
Problemas relacionados a UDAF
-
Sintoma 1: A mensagem de erro Script exception - ValueError: unmarshallable object é retornada.
Causa: O
bufferno código da UDAF Python não é um objeto Marshal.Solução: Ao atribuir um valor ao
buffer, certifique-se de que o valor seja um objeto Marshal. Por exemplo, se você quiser usar doisbuffers dos tipos LIST e DICT em uma Função de Agregação Definida pelo Usuário (UDAF) Python, o métodonew_bufferdeve ser definido comoreturn [list(), dict()]. Ao usarbuffer/pbufferno métodoiterate/merge/terminate, obufferdo tipo LIST corresponde abuffer[0]/pbuffer[0], e obufferdo tipo DICT corresponde abuffer[1]/pbuffer[1]. Se um elemento dobufferfor do tipo LIST ou DICT, o elemento também deverá ser um objeto Marshal.
-
Sintoma 2: A mensagem de erro Python UDAF buffer size overflowed: 2821486749 é retornada.
Causa: O tamanho do
bufferna UDAF Python excede 2 GB após ser processado porMarshal. Obufferestá sendo usado incorretamente. O tamanho dobuffernão deve aumentar proporcionalmente ao volume de dados.Solução: Redesenhe a lógica da UDAF Python. O tamanho do
buffernão deve aumentar com o volume de dados. Por exemplo, se você declarar umbuffercomo umalist, não poderá adicionar dados continuamente aobufferdurante as fasesiterateemerge. Para obter mais informações sobre UDAFs Python, consulte UDAF overview.