Uma introdução (leve) ao gerenciamento de dependências em Python
Lucian Irsigler
14 de setembro de 2021
0 minutos de leituraPython é considerada uma linguagem “simples” — fácil de usar e de desenvolver scripts para realizar diversas tarefas, da raspagem de dados da web à automação, passando pela criação de aplicações web de grande escala e até pela ciência de dados. No entanto, o gerenciamento de dependências em Python é bem diferente do que ocorre em outras linguagens, e as inúmeras opções para configurar um ambiente e usar gerenciadores de pacotes só aumentam a confusão. Neste post, vamos conhecer diferentes maneiras de gerenciar dependências em Python e explorar brevemente a segurança dessas dependências.
Python como linguagem interpretada
Uma linguagem interpretada não tem seu script convertido em código de máquina nem em um executável. Em vez disso, o script passa por outro programa — neste caso, o interpretador Python — que executa o código.
Se eu escrever um script simples em Python como este:
E depois executá-lo com:
Obtemos o seguinte resultado:
Você percebeu que não há arquivos executáveis, como .exe, na pasta em que esse código foi executado? Isso acontece porque o executável do Python compila e executa o arquivo durante a execução, e não antecipadamente.
O detalhe é que há um arquivo .exe executando o código Python. Main.py passa por esse .exe e, em seguida, é executado. Esse arquivo .exe é o interpretador Python compilado, disponível no caminho do seu ambiente.

O que é uma dependência em Python
Uma dependência em Python é como em qualquer outra linguagem: uma biblioteca de código necessária para executar o código-fonte do script que a importou.
Por exemplo, se você quiser interagir com um banco de dados PostgreSQL, há duas opções: escrever todas as funções por conta própria ou instalar o pacote postgres, que já oferece consultas e os outros recursos de que você precisa.
Então, como instalar o pacote PostgreSQL adequado?
Um aspecto importante do gerenciamento de dependências, em qualquer linguagem, é fazer a devida verificação para garantir que o pacote seja bem mantido e não tenha problemas de segurança. Uma maneira de avaliar a integridade geral do pacote é usar o Snyk Advisor.

Com o Snyk Advisor, você pode pesquisar a integridade de pacotes de bibliotecas em diferentes ecossistemas, como PyPI e npm. Também pode analisar imagens base do Docker e consultar estatísticas gerais, popularidade, tags disponíveis e outras informações úteis.
Voltando ao nosso projeto relacionado ao PostgreSQL, vamos conferir se a avaliação de integridade do pacote postgres está dentro de um limite razoável:

Parece que o pacote postgres não tem uma pontuação muito boa: 56 de 100. Ele não é muito popular, com cerca de 10 mil downloads por semana, e seu último lançamento foi há dois anos — um possível sinal de que sua manutenção está deixando a desejar.
Ao rolar a página até as seções de segurança e comunidade, um ponto que chama a atenção é o risco relacionado à licença da versão mais recente do pacote — a versão 3.0.0, de 19 de outubro de 2019 —, que merece uma análise mais cuidadosa:

Se você optar por usar esse pacote, depois de executar a etapa anterior pip install, seu sistema terá acesso ao pacote postgres.
Para importá-lo nos seus projetos:
Agora você já deve perceber como as dependências em Python podem se tornar complicadas. Se eu entregar esse script a um amigo que não tem Python instalado e ele tentar executá-lo, vai encontrar um erro.
Por que ocorre um erro?
Primeiro, seu amigo precisa ter o Python instalado. Além disso, precisa dos pacotes necessários dos quais o projeto depende — neste caso, postgres.
Além disso, o ambiente Python também precisa de todos os módulos necessários para executar o script, assim como acontece em outras linguagens quando falta uma biblioteca específica ou um código-fonte.
Portanto, há dois requisitos para compartilhar meu projeto Python com um amigo:
Todos os arquivos necessários para executar o Python
O pacote
postgres
Gerenciamento de dependências em Python
Ao compartilhar seus projetos Python com alguém, você precisa incluir um arquivo chamado requirements.txt. Use o comando pip para instalar especificamente as dependências exigidas pelo projeto:
Usamos pip3 em vez de apenas pip para garantir que você não instale a versão errada. pip aponta para a versão do Python que você instalou primeiro. Portanto, se você instalou primeiro uma versão do Python 2, o comando pip apontará para pip2, usado para instalar pacotes do Python 2.
Assim, o termo pip3 indica explicitamente ao pip que ele deve instalar o pacote do Python 3.
Se você não tiver nenhuma versão do Python 2 instalada no computador, não precisa se preocupar com isso.
Para conferir qual pip (pip2 ou pip3) seu comando pip está usando, execute isto no console:
Esse comando lê o arquivo de texto requirements.txt, que declara todas as dependências necessárias para o projeto, e depois instala os pacotes listados nele.
Então, para que os pacotes sejam instalados quando alguém executar este comando:
Você precisa criar este arquivo de manifesto de pacotes
O formato das entradas de pacotes nesse arquivo deve seguir este padrão:
<Package name> <Higher/equal to> <some version>
Por exemplo:
Os operadores de comparação são usados para verificar as versões. Eles garantem que o gerenciador de pacotes pip instale as versões corretas para o seu projeto. Se nenhuma versão for especificada, a versão mais recente será instalada.
Agora, se você compartilhar o código-fonte do projeto com seus amigos, basta pedir que executem o comando pip3 com o arquivo requirements.txt incluído no projeto para que tenham as dependências de código aberto necessárias para executá-lo.
E os gerenciadores de dependências para Python?
Além do arquivo de manifesto de pacotes que conhecemos (requirements.txt), há alguns gerenciadores de pacotes que você pode usar para facilitar a manutenção e o gerenciamento das dependências de projetos em Python. Veja algumas opções que você pode instalar e usar:
Poetry
O Poetry permite criar arquivos de lock com as dependências do projeto. O arquivo de lock é instalado automaticamente quando você instala o pacote. A vantagem é que o Poetry facilita a atualização das dependências necessárias para o projeto.
O Poetry funciona com ferramentas de linha de comando. Assim, comandos como:
Esses comandos facilitam o acompanhamento e a inclusão de dependências nesse arquivo de lock, que depois podem ser adicionadas ao seu pacote PyPI.
Você também pode usar a flag --tree para exibir um diagrama em árvore das dependências do seu projeto:
O Poetry facilita o gerenciamento e a inclusão de dependências.
pyenv
O pyenv é uma ferramenta simples que permite alternar entre diferentes versões do Python. Assim, você pode verificar se suas dependências seriam incompatíveis com uma versão anterior do Python. Como esse é seu principal uso, o pyenv não tem os recursos de outros gerenciadores de dependências, como o Poetry.
No entanto, se você precisa de uma ferramenta para verificar se seu pacote funcionaria em uma versão anterior do Python, o pyenv é útil.
Setuptools
Este também é um pacote que ajuda no gerenciamento de pacotes. É um pouco mais trabalhoso do que algo como o Poetry, mas dá conta do recado.
Como o nome indica, o Setuptools ajuda a preparar os usuários para usar seu pacote — ou seja, garante que eles tenham os pacotes corretos para executar o script.
Com o setuptools, você cria dois arquivos: um arquivo pyproject.toml e um arquivo setup.py/setup.cfg.
No arquivo .toml, você insere o seguinte código para informar ao Python que usará o Setuptools para especificar as informações do pacote:
Agora, no arquivo setup.py/setup.cfg, você teria algo assim:
Agora você vai precisar de uma ferramenta de build, como o PyPA build. Seu projeto será compilado em um arquivo .gz, pronto para distribuição.
O Setuptools exige mais trabalho manual da sua parte, mas é eficiente no gerenciamento de pacotes e garante que seus usuários tenham todos os pacotes necessários para executar o script.
Esses três gerenciadores de dependências estão entre as opções mais populares. Cada um tem pontos fortes e fracos. Seja qual for sua escolha, todos funcionam bem e ajudam a simplificar o pesadelo do gerenciamento de dependências em Python.

Melhor ainda: a Snyk CLI mostra o caminho da dependência que leva à vulnerabilidade e também como corrigir o problema — atualizando para uma versão mais recente que inclui uma correção de segurança.
Para concluir
Há outras questões de segurança além das vulnerabilidades em bibliotecas de código aberto. Por exemplo, código inseguro nas suas aplicações Python ou o uso de contêineres inseguros que empacotam suas aplicações Python, entre outros. Daniel Berman escreveu um artigo abrangente sobre como começar a usar a Snyk para desenvolver aplicações Python com segurança, que recomendo muito como complemento a este post.
Espero que você tenha gostado de aprender sobre o gerenciamento de dependências e a segurança em Python. Se quiser ler mais sobre segurança em Python, confira:
Comece a jogar Capture the Flag
Aprenda a resolver desafios de Capture the Flag assistindo à gravação sob demanda do nosso workshop virtual introdutório.
Lucian Irsigler é um programador apaixonado que adora as complexidades da vida.


