Fazendo uma release de um projeto python (manualmente)

Distribuir um projeto python é complicado porque não raramente ele tem vários pacotes com dependências, pensando nisso eu fiz um mini artigo-tutorial sobre como fazer

1) Crie um ambiente virtual

Ele vai colocar em um container tudo que o seu script precisa pra funcionar ou seja, vai facilitar e muito a nossa vida, pra fazer um é extremamente simples, considerando que você já está na sua pasta de trabalho, basta rodar no terminal:

python3 -m venv  . --copies

A flag --copies ancapsua o python

2) Inicie seu ambiente virtual

No passo anterior nós criamos o ambiente virtual mas não o iniciamos, portanto vamos “entrar” nele agora, o seguinte comando inicia o ambiente virtual:

source ./bin/activate

3) Instale seus pacotes

Mesmo que você os tenha instalado no sistema eles não vão (e nem deveriam) ser carregados no ambiente virtual, mas nem se preocupe, a lógica é exatamente a mesma, você vai usar o pip pra instalar, a única diferença é que você vai usar a flag --no-cache-dir :

pip --no-cache-dir install  pacote1 pacote2 pacote3...

Por exemplo, se o seu projeto usa os pacotes request e beautifulsoup4 sua linha ficaria assim:

pip --no-cache-dir install request beautifulsoup4

Fácil né?

4) Crie ou copie o seu script

Sim, se você já fez o seu script e instalou todas as dependências dele, pode só copiar que ele vai funcionar de boas (veja as observações), pra exemplificar vou pegar o script desse tutorial sobre beautifulsoup:

import requests
from bs4 import BeautifulSoup


page = requests.get('https://web.archive.org/web/20121007172955/https://www.nga.gov/collection/anZ1.htm')

soup = BeautifulSoup(page.text, 'html.parser')

last_links = soup.find(class_='AlphaNav')
last_links.decompose()

artist_name_list = soup.find(class_='BodyText')
artist_name_list_items = artist_name_list.find_all('a')

# Usar .contents para pegar as tags <a> filhas
for artist_name in artist_name_list_items:
    names = artist_name.contents[0]
    print(names)

Nota: seu script não deve fazer chamadas para caminhos absolutos

5) Teste

Obviamente você precisa testar o seu script, basta chamar ele assim:

python3 seu_script.py

Assim como faria fora do ambiente virtual

6) Deixe seu ambiente Python portável

O ambiente funciona mas tem um problema, se você mandar ele pra outra pessoa ou mover seu ambiente pra outra pasta ele não vai funcionar, isso acontece porque atualmente ele está usando um caminho absoluto pra carregar o ambiente, pra resolver isso, use os seguintes comandos:

  1. Primeiro vamos adicionar a shebang “#!/usr/bin/env bash” no arquivo bin/activate e redirecionar a saída para bin/python3.wrap
echo '#!/usr/bin/env bash' | cat - bin/activate > bin/python3.wrap
  1. Aqui vai a mágica nós vamos substituir o caminho absoluto pela saída do comando $(dirname $(dirname $(readlink -f $0))) no arquivo bin/python3.wrap, ele pega o diretório superior de onde o script está
sed -i "s|$(pwd)|\$\(dirname \$\(dirname \$\(readlink -f \$0\)\)\)|" python3
  1. Agora nós adicionamos a chamada ao python ou seja vamos chamar o python que nós encapsumalos no passo 1:
echo '$VIRTUAL_ENV/bin/python3 ${@}' >> bin/python3.wrap
  1. Por fim nós vamos assegurar que bin/python3.wrap possa ser execuutado:
chmod +x bin/python3.wrap

Ok, mas todo esse trabalho pra que? Bem, atualmente pra nós rodarmos nosso script nós precisamos fazer isso:

source ./bin/activate
python3 seu_script.py

E ainda temos outro problema, se nós não executarmos esses comandos no exato caminho codificado em bin/activate nosso ambiente não vai funcionar, agora já ficou beeem mais simples, basta digitar:

./bin/python3 seu_script.py

E o ambiente virtual pode ser executado a partir de qualquer diretório, mas não é o suficinte

5) Criando um AppDir

Um AppDir é um diretório que contém todos os arquivos que uma aplicação precisa pra funcionar, atualmente nós tempos quase tudo faltando apenas o arquivo AppRun, ele é o responsável por iniciar o aplicativo, é um jeio padronizado de fazer, como o python configurou tudo em bin/activate nós basicamente só precisamos chamar o bin/python3.wrap, basta criar um arquivo chamado “AppRun” com esse modelo:

#!/bin/sh
HERE="$(dirname "$(readlink -f "${0}")")"
export PATH="${HERE}"/usr/bin/:"${HERE}"/usr/sbin/:"${HERE}"/usr/games/:"${HERE}"/bin/:"${HERE}"/sbin/:"${PATH}"
export LD_LIBRARY_PATH="${HERE}"/usr/lib/:"${HERE}"/usr/lib/i386-linux-gnu/:"${HERE}"/usr/lib/x86_64-linux-gnu/:"${HERE}"/usr/lib32/:"${HERE}"/usr/lib64/:"${HERE}"/lib/:"${HERE}"/lib/i386-linux-gnu/:"${HERE}"/lib/x86_64-linux-gnu/:"${HERE}"/lib32/:"${HERE}"/lib64/:"${LD_LIBRARY_PATH}"
export XDG_DATA_DIRS="${HERE}"/usr/share/:"${XDG_DATA_DIRS}"
export PERLLIB="${HERE}"/usr/share/perl5/:"${HERE}"/usr/lib/perl5/:"${PERLLIB}"
export GSETTINGS_SCHEMA_DIR="${HERE}"/usr/share/glib-2.0/schemas/:"${GSETTINGS_SCHEMA_DIR}"
export QT_PLUGIN_PATH="${HERE}"/usr/lib/qt4/plugins/:"${HERE}"/usr/lib/i386-linux-gnu/qt4/plugins/:"${HERE}"/usr/lib/x86_64-linux-gnu/qt4/plugins/:"${HERE}"/usr/lib32/qt4/plugins/:"${HERE}"/usr/lib64/qt4/plugins/:"${HERE}"/usr/lib/qt5/plugins/:"${HERE}"/usr/lib/i386-linux-gnu/qt5/plugins/:"${HERE}"/usr/lib/x86_64-linux-gnu/qt5/plugins/:"${HERE}"/usr/lib32/qt5/plugins/:"${HERE}"/usr/lib64/qt5/plugins/:"${QT_PLUGIN_PATH}"

Agora você adiciona no final desse arquivo:

echo -e "\n" '$HERE/bin/python3 $HERE/seu_script.py "$@"' >> AppRun

Obviamente substituindo seu_script.py pelo nome do arquivo do seu script.

Pra finalizar basta tornar o arquivo AppRun executável:

chmod a+x AppRun

6) O que vem depois depende do que você quer

Agora (considerando que você esteja na pasta do ambiente virtual) você pode executar o script assim:

./AppRun

E isso abre um leque imenso de posibilidades, a partir daqui você pode fazer um AppImage, um Snap, um Flatpak, um tarball, um .deb, um .rpm… enfim, qualquer coisa

Espero que tenha sido útil e até a próxima

4 Curtidas