Todos os produtos
Search
Central de documentação

MaxCompute:Referenciar um pacote de terceiros em um nó PyODPS

Última atualização: Jun 26, 2026

Use pacotes Python de terceiros, como SciPy ou python-dateutil, no PyODPS. Para isso, carregue-os como recursos do MaxCompute e referencie-os no código. Para obter instruções sobre como gerar um pacote com pyodps-pack, consulte Gerar um pacote de terceiros para PyODPS.

Pré-requisitos

Antes de começar, verifique se você tem:

Escolha um método

Selecione o método adequado ao seu cenário:

Cenário

Método recomendado

Novo projeto, UDF Python ou DataFrame

Use pyodps-pack para empacotar e carregar; depois, referencie via sys.path ou pelo parâmetro libraries

Nó PyODPS no DataWorks com pacotes integrados

Use o método nativo do DataWorks ou load_resource_package

Projeto existente com arquivos WHL carregados manualmente

Carregamento manual (apenas para manutenção legada; use pyodps-pack em novos projetos)

Carregar um pacote de terceiros

Antes de referenciar um pacote de terceiros, carregue-o no MaxCompute como recurso de arquivo compactado. Use um dos métodos a seguir:

  • Carregamento via código. Substitua packages.tar.gz pelo caminho e nome do seu arquivo de pacote.

    import os
    from odps import ODPS
    
    # Load credentials from environment variables.
    # Avoid hardcoding your AccessKey ID or AccessKey secret in code.
    o = ODPS(
        os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'),
        os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
        project='<your-default-project>',
        endpoint='<your-end-point>',
    )
    o.create_resource("test_packed.tar.gz", "archive", fileobj=open("packages.tar.gz", "rb"))
  • Carregamento via DataWorks. Consulte Etapa 1: Criar um recurso ou fazer upload de um recurso existente.

Referenciar um pacote de terceiros em uma UDF Python

Para usar um pacote de terceiros em uma função definida pelo usuário (UDF) Python, modifique a classe da UDF:

  1. Adicione o caminho do pacote ao sys.path no método __init__.

  2. Insira a instrução de importação no corpo da função (na função evaluate ou no método process).

Importante

A instrução de importação deve ficar no corpo da função, não no início do arquivo. Os pacotes de terceiros ficam disponíveis apenas durante a execução. Quando o MaxCompute analisa a UDF, o ambiente de análise não inclui esses pacotes. Por isso, uma importação no nível superior causa erro.

Exemplo: usar SciPy em uma UDF

Este exemplo usa a função psi do SciPy em uma UDF.

  1. Empacote o SciPy.

    pyodps-pack -o scipy-bundle.tar.gz scipy
  2. Escreva o código da UDF e salve-o como test_psi_udf.py.

    import sys
    from odps.udf import annotate
    
    @annotate("double->double")
    class MyPsi(object):
        def __init__(self):
            # Add the package path to sys.path.
            # MaxCompute decompresses archive resources into folders under the work/ directory.
            # The folder name matches the resource name.
            # packages/ is the subdirectory created by pyodps-pack.
            sys.path.insert(0, "work/scipy-bundle.tar.gz/packages")
    
        def evaluate(self, arg0):
            # Place the import statement inside the function body.
            from scipy.special import psi
    
            return float(psi(arg0))
  3. Carregue test_psi_udf.py como recurso Python e scipy-bundle.tar.gz como recurso de arquivo compactado.

  4. Crie a UDF, referencie ambos os recursos e defina o nome da classe como test_psi_udf.MyPsi. Execute essa etapa em um nó PyODPS ou no cliente MaxCompute.

    • Em um nó PyODPS:

      import os
      from odps import ODPS
      
      # Load credentials from environment variables.
      # Avoid hardcoding your AccessKey ID or AccessKey secret in code.
      o = ODPS(
          os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'),
          os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
          project='<your-default-project>',
          endpoint='<your-end-point>',
      )
      
      bundle_res = o.create_resource(
          "scipy-bundle.tar.gz", "archive", fileobj=open("scipy-bundle.tar.gz", "rb")
      )
      udf_res = o.create_resource(
          "test_psi_udf.py", "py", fileobj=open("test_psi_udf.py", "rb")
      )
      o.create_function(
          "test_psi_udf", class_type="test_psi_udf.MyPsi", resources=[bundle_res, udf_res]
      )
    • No cliente MaxCompute:

      add archive scipy-bundle.tar.gz;
      add py test_psi_udf.py;
      create function test_psi_udf as test_psi_udf.MyPsi using test_psi_udf.py,scipy-bundle.tar.gz;
  5. Execute a UDF em uma instrução SQL.

    set odps.pypy.enabled=false;
    set odps.isolation.session.enable=true;
    select test_psi_udf(sepal_length) from iris;

Referenciar um pacote de terceiros no PyODPS DataFrame

Passe o parâmetro libraries para o método execute ou persist. O exemplo a seguir usa o método map. O procedimento é o mesmo para os métodos apply e map_reduce.

  1. Empacote o SciPy.

    pyodps-pack -o scipy-bundle.tar.gz scipy
  2. Execute o código a seguir para aplicar o pacote a uma operação de DataFrame. Este exemplo calcula psi(col1) em uma tabela chamada test_float_col, que possui uma única coluna do tipo FLOAT.

    import os
    from odps import ODPS, options
    
    def my_psi(v):
        from scipy.special import psi
    
        return float(psi(v))
    
    # Skip this setting if isolation is already enabled for your project.
    options.sql.settings = {"odps.isolation.session.enable": True}
    
    # Load credentials from environment variables.
    # Avoid hardcoding your AccessKey ID or AccessKey secret in code.
    o = ODPS(
        os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'),
        os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
        project='<your-default-project>',
        endpoint='<your-end-point>',
    )
    df = o.get_table("test_float_col").to_df()
    
    # Execute and return the result.
    df.col1.map(my_psi).execute(libraries=["scipy-bundle.tar.gz"])
    
    # Save the result to another table.
    df.col1.map(my_psi).persist("result_table", libraries=["scipy-bundle.tar.gz"])

    Os dados de entrada têm o seguinte formato:

       col1
    0  3.75
    1  2.51
  3. (Opcional) Para usar o mesmo pacote em todas as operações de DataFrame na sessão, defina o parâmetro global.

    from odps import options
    options.df.libraries = ["scipy-bundle.tar.gz"]

Referenciar um pacote de terceiros no DataWorks

Um nó PyODPS do DataWorks fornece pacotes de terceiros integrados. Para usar um pacote não nativo, chame o método load_resource_package. Para mais detalhes, consulte Usar um pacote de terceiros.

Carregar e referenciar manualmente um pacote de terceiros

Siga estas instruções apenas para projetos existentes que já usam dependências WHL carregadas manualmente ou para ambientes com uma versão antiga do MaxCompute sem suporte a pacotes binários. Para novos projetos, use pyodps-pack .

Este exemplo usa python-dateutil no método map.

  1. Baixe o python-dateutil e suas dependências para um diretório local. Execute este comando no Linux para garantir a compatibilidade dos pacotes com o sistema operacional Linux.

    pip download python-dateutil -d /to/path/

    Dois pacotes são baixados: six-1.10.0-py2.py3-none-any.whl e python_dateutil-2.5.3-py2.py3-none-any.whl.

  2. Carregue os pacotes no MaxCompute.

    • Método 1: Usar código.

      # Make sure the file name extensions are valid.
      odps.create_resource('six.whl', 'file', file_obj=open('six-1.10.0-py2.py3-none-any.whl', 'rb'))
      odps.create_resource('python_dateutil.whl', 'file', file_obj=open('python_dateutil-2.5.3-py2.py3-none-any.whl', 'rb'))
    • Método 2: Usar DataWorks. Consulte Etapa 1: Criar um recurso ou fazer upload de um recurso existente.

  3. Referencie os pacotes no código. Este exemplo analisa strings de data de uma coluna de DataFrame.

    • Definir bibliotecas globalmente:

      from odps import options
      
      def get_year(t):
          from dateutil.parser import parse
          return parse(t).strftime('%Y')
      
      options.df.libraries = ['six.whl', 'python_dateutil.whl']
      df.datestr.map(get_year).execute()

      Saída:

         datestr
      0     2016
      1     2015
    • Passar bibliotecas por chamada:

      def get_year(t):
          from dateutil.parser import parse
          return parse(t).strftime('%Y')
      
      df.datestr.map(get_year).execute(libraries=['six.whl', 'python_dateutil.whl'])

      Saída:

         datestr
      0     2016
      1     2015

Compatibilidade de pacotes binários

Por padrão, o PyODPS oferece suporte a bibliotecas Python que contêm apenas código Python, sem operações de arquivo. Versões mais recentes do MaxCompute também aceitam bibliotecas com código binário ou operações de arquivo. Os nomes das bibliotecas devem incluir um sufixo específico da plataforma.

A tabela a seguir lista os sufixos suportados por plataforma e versão do Python.

Plataforma

Versão do Python

Sufixo suportado

RHEL 5 x86_64

Python 2.7

cp27-cp27m-manylinux1_x86_64

RHEL 5 x86_64

Python 3.7

cp37-cp37m-manylinux1_x86_64

RHEL 7 x86_64

Python 2.7

cp27-cp27m-manylinux1_x86_64, cp27-cp27m-manylinux2010_x86_64, cp27-cp27m-manylinux2014_x86_64

RHEL 7 x86_64

Python 3.7

cp37-cp37m-manylinux1_x86_64, cp37-cp37m-manylinux2010_x86_64, cp37-cp37m-manylinux2014_x86_64

RHEL 7 Arm64

Python 3.7

cp37-cp37m-manylinux2014_aarch64

Todos os pacotes WHL devem ser carregados no MaxCompute como recursos de arquivo compactado. Antes do carregamento, renomeie cada arquivo WHL para ZIP alterando sua extensão. Além disso, defina odps.isolation.session.enable como True para o job ou para o projeto.

O exemplo a seguir carrega e usa o SciPy como pacote binário.

# Binary packages must be uploaded as archive resources.
# Rename the .whl file to .zip before uploading.
odps.create_resource('scipy.zip', 'archive', file_obj=open('scipy-0.19.0-cp27-cp27m-manylinux1_x86_64.whl', 'rb'))

# Skip this setting if isolation is already enabled for your project.
options.sql.settings = { 'odps.isolation.session.enable': True }

def my_psi(value):
    # Place the import statement inside the function to avoid runtime errors
    # caused by structural differences in binary packages across operating systems.
    from scipy.special import psi
    return float(psi(value))

df.float_col.map(my_psi).execute(libraries=['scipy.zip'])

Para empacotar pacotes binários baseados apenas em código-fonte em arquivos WHL, execute o comando a seguir no Linux. Arquivos WHL compilados no macOS ou Windows não funcionam no MaxCompute.

python setup.py bdist_wheel