O MaxCompute permite usar pacotes de terceiros em funções definidas pelo usuário (UDF) Python, como o pacote NumPy, pacotes que exigem compilação ou aqueles que dependem de bibliotecas de link dinâmico. Este tópico demonstra como utilizá-los.
Informações básicas
Você pode usar pacotes de terceiros em uma UDF Python nos seguintes cenários:
-
Usar o pacote NumPy (UDFs Python 3)
Altere a extensão do arquivo do pacote NumPy, faça upload do pacote com o cliente MaxCompute e registre a função para chamá-la posteriormente em sua UDF Python 3.
-
Usar um pacote de terceiros que exige compilação
Em um ambiente compatível com o MaxCompute, compile o script setup.py do pacote de terceiros para gerar um pacote wheel e altere a extensão do arquivo. Em seguida, use o cliente MaxCompute para fazer upload do pacote e registrar a função, permitindo sua chamada na UDF Python.
-
Usar um pacote de terceiros dependente de biblioteca de link dinâmico
Compile um arquivo de biblioteca .so a partir do código-fonte do pacote de terceiros, gere um pacote wheel e altere a extensão do arquivo. Depois, use o cliente MaxCompute para fazer upload tanto do pacote quanto do arquivo de biblioteca .so e registre a função para possibilitar sua chamada na UDF Python.
Pré-requisitos
Antes de começar, verifique se os seguintes requisitos foram atendidos:
O Python está instalado. Recomenda-se o Python 3.
O cliente MaxCompute está instalado e configurado. Para mais informações, consulte Instalar e configurar o cliente MaxCompute.
Para pacotes que exigem compilação, garanta que pip, setuptools e wheel estejam instalados. Execute o comando
pip install setuptoolspara instalar o setuptools e o comandopip install wheelpara instalar o wheel.Se você usar GDAL 3.0 ou superior, certifique-se de que o PROJ 6 esteja instalado.
Se for usar docker para compilar um pacote de terceiros, verifique se o docker está instalado. Para mais detalhes, consulte a documentação de instalação do docker.
Usar o pacote NumPy (UDFs Python 3)
O ambiente Python 2 do MaxCompute já inclui o NumPy por padrão. Para usar o pacote NumPy em uma UDF Python 3, faça o upload manual do pacote seguindo estas etapas:
-
Tomando a versão 1.19.2 como exemplo, acesse a página do PyPI. Na seção Download files, baixe o pacote NumPy cujo nome de arquivo termina com cp37-cp37m-manylinux1_x86_64.whl.
NotaO carregamento pode falhar se você usar um pacote com uma extensão de arquivo diferente. Caso deseje usar outra versão, vá até a seção Navigation no canto superior esquerdo da página do PyPI e clique em Release history para visualizar as versões anteriores.
-
Altere a extensão do arquivo do pacote NumPy baixado para .zip.
Exemplo: numpy-1.19.2-cp37-cp37m-manylinux1_x86_64.zip.
-
Use o cliente MaxCompute para fazer upload do pacote NumPy para um projeto MaxCompute. Para mais informações sobre como fazer upload de um recurso, consulte Operações de recursos.
Comando de exemplo:
ADD ARCHIVE D:\Downloads\numpy-1.19.2-cp37-cp37m-manylinux1_x86_64.zip -f; -
Escreva um script de UDF Python e salve-o como um arquivo .py.
Abaixo está um exemplo de script de UDF Python salvo como import_numpy.py:
from odps.udf import annotate @annotate("->string") class TryImport(object): # The class name is TryImport. def __init__(self): import sys sys.path.insert(0, 'work/numpy-1.19.2-cp37-cp37m-manylinux1_x86_64.zip') # The NumPy package. You only need to replace the package name that follows work/. def evaluate(self): import numpy return "import succeed" -
Use o cliente MaxCompute para fazer upload do script import_numpy.py como um recurso no seu projeto MaxCompute.
Comando de exemplo:
ADD PY D:\Desktop\import_numpy.py -f; -
Use o script import_numpy.py e o pacote NumPy enviados para registrar uma função definida pelo usuário por meio do cliente MaxCompute. Para mais informações sobre como registrar uma função, consulte Operações de funções.
Suponha que a função definida pelo usuário registrada se chame numpy e que o recurso da função esteja localizado no projeto test_project. Comando de exemplo:
CREATE FUNCTION numpy AS 'import_numpy.TryImport' USING 'test_project/resources/import_numpy.py,numpy-1.19.2-cp37-cp37m-manylinux1_x86_64.zip';NotaAo registrar a função, adicione o pacote NumPy, como numpy-1.19.2-cp37-cp37m-manylinux1_x86_64.zip, à lista de recursos.
Após registrar a função, chame-a nas suas instruções SQL. Certifique-se de ativar o Python 3 para execução. Para mais informações, consulte Especificações e fluxo de trabalho de desenvolvimento de UDF Python 3.
Usar pacotes que exigem compilação
Se um pacote de terceiros for um arquivo TAR.GZ do PyPI ou um pacote de código-fonte do GitHub, o diretório raiz do pacote descompactado poderá conter um arquivo setup.py. Antes de usar esse tipo de pacote, compile o arquivo setup.py para gerar um pacote wheel em um ambiente compatível com o MaxCompute. Em seguida, faça upload do recurso e registre a função. Assim, será possível chamar o pacote de terceiros usando uma UDF Python. Para mais informações sobre upload de recursos e registro de funções, consulte Usar o pacote NumPy (UDFs Python 3).
Pacotes de terceiros são executados em um ambiente Linux no MaxCompute. Para evitar problemas de compatibilidade, compile-os em um ambiente Linux em vez de Windows.
Caso use um ambiente Windows, recomenda-se usar a versão correspondente do Python (
/opt/python/cp27-cp27m/bin/pythonou/opt/python/cp37-cp37m/bin/python3) para criar um pacote wheel no contêinerquay.io/pypa/manylinux2010_x86_64do docker.
Se estiver usando um ambiente Linux, verifique os pontos abaixo para garantir a compatibilidade:
-
Use uma versão compatível do Python. Na interface de linha de comando (CLI) do seu sistema, execute o seguinte comando para verificar a compatibilidade da sua versão do Python:
python -c "import wheel.pep425tags; print(wheel.pep425tags.get_abi_tag())"Se o retorno for
cp27moucp37m, a versão do Python atende aos requisitos de compatibilidade.Se o retorno for
cp27muoucp37mu, a versão do Python não atende aos requisitos de compatibilidade. Execute o comando./configure --enable-unicode=ucs2na CLI para definir a codificação do Python como UCS-2.
-
Caso existam dependências de código C ou C++, use uma versão compatível do GNU Compiler Collection (GCC).
NotaRecomenda-se o uso do GCC 4.9.2 ou anterior. Se usar uma versão do GCC posterior à 4.9.2, os arquivos .so no pacote wheel gerado podem ser incompatíveis com o ambiente MaxCompute.
Depois que seu ambiente atender aos requisitos de compatibilidade, siga estas etapas para gerar um pacote wheel a partir de um arquivo setup.py:
-
Extraia o pacote de terceiros para um diretório local. Na CLI do seu sistema, navegue até a pasta onde o arquivo setup.py está localizado.
Por exemplo, se você baixar e extrair o pacote GDAL-3.2.0.zip, o arquivo setup.py estará no diretório D:\Downloads\GDAL-3.2.0. Comando de exemplo:
cd D:\Downloads\GDAL-3.2.0 -
Na CLI, execute o comando a seguir para verificar se bdist_wheel consta na saída.
Comando de exemplo:
python setup.py --help-command -
Na CLI, execute o comando a seguir para compilar e gerar um pacote wheel.
python setup.py bdist_wheelNotaO pacote wheel encontra-se no diretório dist.
Usar pacotes com bibliotecas de link dinâmico
Alguns pacotes Python de terceiros podem depender de outras bibliotecas de link dinâmico além das bibliotecas Python. Esta seção usa o GDAL 3.0.4 como exemplo para descrever como usar o contêiner docker quay.io/pypa/manylinux2010_x86_64 para compilar os arquivos de biblioteca .so relevantes e gerar um pacote wheel utilizável no MaxCompute. Posteriormente, use esses arquivos gerados para fazer upload como recursos e registrar a função, permitindo chamar o pacote a partir de uma UDF Python. Para mais informações sobre como fazer upload de um recurso e registrar uma função, consulte Usar o pacote NumPy (UDFs Python 3).
Certifique-se de que o docker esteja instalado antes de prosseguir. Para mais informações sobre operações do docker, consulte a documentação do docker.
Para usar um pacote de terceiros que depende de um arquivo de biblioteca .so em uma UDF Python, siga estas etapas:
-
Visualize as dependências. Consulte a seção Dependencies na página do PyPI.
Por exemplo, as dependências do GDAL 3.0.4 são as seguintes:
Dependencies - libgdal (3.0.4 or greater) and header files (gdal-devel) - numpy (1.0.0 or greater) and header files (numpy-devel) (not explicitly required, but many examples and utilities will not work without it)NotaConforme mostrado acima, as dependências incluem libgdal e numpy. O libgdal é obtido compilando o código-fonte do GDAL em um contêiner, e o numpy é obtido baixando o pacote NumPy da página do PyPI ou em um contêiner docker.
-
Baixe o pacote NumPy.
Baixe o pacote NumPy usando um dos métodos a seguir:
-
Na página do PyPI, vá até a seção Download files e baixe o pacote NumPy cujo nome de arquivo termina com cp37-cp37m-manylinux1_x86_64.whl.
NotaSe estiver usando um ambiente Python 2, baixe um pacote NumPy compatível. Na área Navigation no lado esquerdo da página do PyPI, clique em Release history, selecione a versão 1.16.6 ou anterior e baixe o pacote cujo nome de arquivo termina com cp27-cp27m-manylinux1_x86_64.whl.
No contêiner docker quay.io/pypa/manylinux2010_x86_64, execute o comando
/opt/python/cp37-cp37m/bin/pip download numpy -d ./para baixar o pacote NumPy no diretório atual.
-
-
Compile o arquivo de biblioteca .so.
Baixe o código-fonte do GDAL 3.0.4 e extraia-o para um diretório local.
-
Use o docker para obter a imagem do contêiner quay.io/pypa/manylinux2010_x86_64 e entrar no modo de terminal interativo.
Comandos de exemplo:
docker pull quay.io/pypa/manylinux2010_x86_64 docker run -it quay.io/pypa/manylinux2010_x86_64 /bin/bash -
Copie o código-fonte do GDAL 3.0.4 para o contêiner.
Comando de exemplo:
docker cp ./gdal-3.0.4 <CONTAINER ID>:/opt/source/Para obter o CONTAINER ID, consulte docker ps.
-
Compile o GDAL 3.0.4 no contêiner. Para mais informações, consulte BuildingOnUnix.
Comandos de exemplo:
# You must specify the installation directory of PROJ 6 in the configure option. ./configure --prefix=/path/to/install/prefix --with-proj=/path/to/install/proj6/prefix make make install export PATH=/path/to/install/prefix/bin:$PATH export LD_LIBRARY_PATH=/path/to/install/prefix/lib:$LD_LIBRARY_PATH export GDAL_DATA=/path/to/install/prefix/share/gdal # Test gdalinfo --versionOs seguintes erros podem ocorrer durante a compilação:
configure: error: PROJ 6 symbols not found: O GDAL 3.0 e versões posteriores dependem do PROJ 6. Baixe e instale o PROJ 6.fatal error: zlib.h: No such file or directory: Execute o comandoyum install zlib-devele compile novamente.
Use o comando docker cp para copiar os arquivos libgdal.so e libproj.so do contêiner para sua máquina local. Eles estão localizados na pasta lib de seus respectivos diretórios de instalação. Certifique-se de copiar os arquivos reais, e não seus links simbólicos.
-
Crie um pacote wheel do GDAL no contêiner. Para mais informações, consulte BuildingOnUnix.
Comandos de exemplo:
# If NumPy is required, you must install NumPy first. /opt/python/cp37-cp37m/bin/pip install numpy # Switch to the directory of the GDAL source code. cd swig/python # A wheel package is generated in the dist directory. Example: GDAL-3.0.4-cp37-cp37m-linux_x86_64.whl /opt/python/cp37-cp37m/bin/python setup.py bdist_wheel -
Com base nos arquivos de biblioteca .so, no pacote wheel ou no pacote NumPy gerados, faça upload dos recursos e registre a função para usar o pacote de terceiros em uma UDF Python. Para mais informações sobre como fazer upload de recursos e registrar uma função, consulte Usar o pacote NumPy (UDFs Python 3).
Observe os seguintes pontos:
Ao fazer upload de recursos, envie libgdal.so e libproj.so como recursos FILE, e envie numpy-1.19.2-cp37-cp37m-manylinux1_x86_64.zip e GDAL-3.0.4-cp37-cp37m-linux_x86_64.zip como recursos ARCHIVE.
Ao registrar a função, adicione libgdal.so, libproj.so, numpy-1.19.2-cp37-cp37m-manylinux1_x86_64.zip e GDAL-3.0.4-cp37-cp37m-linux_x86_64.zip à lista de recursos da função.
Segue um exemplo de código para a UDF Python:
NotaEste exemplo usa código Python 3 e deve ser executado em um ambiente Python 3. Se precisar executá-lo em um ambiente Python 2, atente-se ao uso do parâmetro
get_cache_file. Para mais informações, consulte Recursos de referência.# coding: utf-8 from odps.udf import annotate from odps.distcache import get_cache_file def include_file(file_name): import os, sys so_file = get_cache_file(file_name, 'b') with open(so_file.name, 'rb') as fp: content=fp.read() so = open(file_name, "wb") so.write(content) so.flush() so.close() @annotate("->string") class TryImport(object): def __init__(self): import sys include_file('libgdal.so.26') include_file('libproj.so.15') sys.path.insert(0, 'work/GDAL-3.0.4-cp37-cp37m-linux_x86_64.zip') # The compiled GDAL package. You only need to replace the package name that follows work/. sys.path.insert(0, 'work/numpy-1.19.2-cp37-cp37m-manylinux1_x86_64.zip') # The NumPy package. You only need to replace the package name that follows work/. def evaluate(self): from osgeo import gdal from osgeo import ogr from osgeo import osr from osgeo import gdal_array from osgeo import gdalconst return "import succeed"NotaSe encontrar um erro de execução indicando que libgdal.so.26 ou libproj.so.15 não foi encontrado, renomeie os arquivos libgdal.so e libproj.so enviados para libgdal.so.26 e libproj.so.15, respectivamente.