Visão geral do empacotamento para Python#

Como uma linguagem de programação de propósito geral, Python foi projetado para ser usado de várias maneiras. Você pode construir sites ou robôs industriais ou um jogo para seus amigos jogarem e muito mais, todos usando a mesma tecnologia básica.

A flexibilidade do Python é o porquê do primeiro passo em cada projeto Python deva ser pensar sobre o público do projeto e o ambiente correspondente onde o projeto será executado. Pode parecer estranho pensar em empacotamento antes de escrever o código, mas esse processo faz maravilhas para evitar dores de cabeça futuras.

Esta visão geral fornece uma árvore de decisão de propósito geral para raciocinar sobre a abundância de opções de empacotamento do Python. Continue lendo para escolher a melhor tecnologia para seu próximo projeto.

Pensando sobre a implantação#

Os pacotes existem para serem instalados (ou implantados, deployed), portanto, antes de empacotar qualquer coisa, você vai querer ter algumas respostas para as perguntas de implantação abaixo:

  • Quem são os usuários do seu software? Seu software será instalado por outros desenvolvedores que fazem o desenvolvimento de software, pessoas de operações em um datacenter ou um grupo com menos experiência em software?

  • O seu software deve ser executado em servidores, desktops, clientes móveis (telefones, tablets, etc.) ou incorporado em dispositivos dedicados?

  • O seu software é instalado individualmente ou em grandes lotes de implantação?

O empacotamento tem tudo a ver com o ambiente de destino e a experiência de implantação. Existem muitas respostas para as perguntas acima e cada combinação de circunstâncias tem suas próprias soluções. Com essas informações, a visão geral a seguir o guiará para as tecnologias de empacotamento mais adequadas ao seu projeto.

Empacotando bibliotecas e ferramentas Python#

Você deve ter ouvido falar sobre PyPI, setup.py e arquivos wheel. Estas são apenas algumas das ferramentas que o ecossistema Python oferece para distribuir código Python para desenvolvedores, sobre as quais você pode ler em Empacotando e distribuindo projetos.

As abordagens a seguir para empacotamento são destinadas a bibliotecas e ferramentas usadas pelo público técnico em um ambiente de desenvolvimento. Se você está procurando maneiras de empacotar Python para um público não técnico e/ou uma configuração de produção, pule para Empacotando aplicações do Python.

Módulos Python#

Um arquivo Python, desde que dependa apenas da biblioteca padrão, pode ser redistribuído e reutilizado. Você também precisará garantir que ele foi escrito para a versão correta do Python e depende apenas da biblioteca padrão.

Isso é ótimo para compartilhar scripts e trechos simples entre pessoas que possuem versões Python compatíveis (como via e-mail, StackOverflow ou gists do GitHub). Existem até algumas bibliotecas Python inteiras que oferecem isso como uma opção, como bottle.py e boltons.

No entanto, esse padrão não será escalonado para projetos que consistem em vários arquivos, precisam de bibliotecas adicionais ou precisam de uma versão específica do Python, daí as opções abaixo.

Distribuições fonte Python#

Se o seu código consiste em vários arquivos Python, ele geralmente é organizado em uma estrutura de diretório. Qualquer diretório contendo arquivos Python pode incluir um Pacote de Importação.

Como os pacotes consistem em vários arquivos, eles são mais difíceis de distribuir. A maioria dos protocolos oferece suporte à transferência de apenas um arquivo por vez (quando foi a última vez que você clicou em um link e ele baixou vários arquivos?). É mais fácil obter transferências incompletas e mais difícil garantir a integridade do código no destino.

Contanto que seu código não contenha nada além de código puro Python, e você saiba que seu ambiente de implantação oferece suporte a sua versão de Python, então você pode usar as ferramentas de empacotamento nativas do Python para criar um Pacote de Distribuição fonte, ou sdist.

Os sdists do Python são arquivos compactados (arquivos .tar.gz) contendo um ou mais pacotes ou módulos. Se seu código for puro Python e você depender apenas de outros pacotes Python, você pode consultar a especificação de Formato de distribuição fonte para saber mais.

Se você confiar em qualquer código não-Python ou pacotes não-Python (como libxml2 no caso de lxml, ou bibliotecas BLAS no caso de numpy), você precisará usar o formato detalhado no a próxima seção, que também tem muitas vantagens para bibliotecas puro Python.

Nota

Python e PyPI oferecem suporte a várias distribuições, fornecendo diferentes implementações do mesmo pacote. Por exemplo, a distribuição PIL não mantida, mas inspiracional, fornece o pacote PIL, e também o Pillow, um fork do PIL!

Este superpoder de empacotamento do Python torna possível que o Pillow seja um substituto imediato para o PIL, apenas alterando o install_requires ou requirements.txt do seu projeto.

Distribuições binárias Python#

Grande parte do poder prático do Python vem de sua capacidade de integração com o ecossistema de software, em particular bibliotecas escritas em C, C++, Fortran, Rust e outras linguagens.

Nem todos os desenvolvedores têm as ferramentas ou experiências certas para construir esses componentes escritos nessas linguagens compiladas, então Python criou o Wheel, um formato de pacote projetado para enviar bibliotecas com artefatos compilados. Na verdade, o instalador do pacote Python, pip, sempre prefere wheels porque a instalação é sempre mais rápida, então mesmo os pacotes puro Python funcionam melhor com wheels.

As distribuições binárias são melhores quando vêm com distribuições de fonte correspondentes. Mesmo que você não envie wheels do seu código para todos os sistemas operacionais, ao enviar o sdist, você permite que usuários de outras plataformas ainda o construam por conta própria. O padrão é publicar arquivos sdist e wheel juntos, a menos que você esteja criando artefatos para um caso de uso muito específico, onde sabe que o destinatário só precisa de um ou de outro.

Python e PyPI facilitam o envio de wheels e sdists juntos. Basta seguir o tutorial Empacotando projetos Python.

Um resumo das capacidades de empacotamento do Python para ferramentas e bibliotecas.

Bibliotecas embutidas recomendadas e tecnologias de empacotamento de ferramentas do Python. Extraído de The Packaging Gradient (2017).#

Empacotando aplicações do Python#

Até agora, discutimos apenas as ferramentas de distribuição nativas do Python. Com base em nossa introdução, você estaria correto em inferir que essas abordagens embutidas têm como alvo apenas ambientes que possuem Python e um público que sabe como instalar pacotes Python.

Com a variedade de sistemas operacionais, configurações e pessoas por aí, essa suposição só é segura quando se destina a um público de desenvolvedores.

O empacotamento nativo do Python é construído principalmente para distribuir código reutilizável, chamado de bibliotecas, entre os desenvolvedores. Você pode adicionar ferramentas ou aplicações básicas para desenvolvedores ao pacote de biblioteca do Python, usando tecnologias como entry_points do setuptools.

Bibliotecas são blocos de construção, não aplicações completas. Para distribuir aplicações, existe um novo mundo de tecnologias por aí.

As próximas seções organizam essas opções de pacote de aplicações de acordo com suas dependências no ambiente de destino, para que você possa escolher o certo para o seu projeto.

Dependendo de um framework#

Alguns tipos de aplicações Python, como backends de sites e outros serviços de rede, são comuns o suficiente para que tenham estruturas para permitir seu desenvolvimento e empacotamento. Outros tipos de aplicações, como frontends web dinâmicos e clientes móveis, são complexos o suficiente para fazer com que uma estrutura se torne mais do que uma conveniência.

Em todos esses casos, faz sentido trabalhar de trás para frente, a partir da história de empacotamento e implantação da estrutura. Algumas estruturas incluem um sistema de implantação que envolve as tecnologias descritas no restante do guia. Nesses casos, você desejará consultar o guia de empacotamento de sua estrutura para obter a experiência de produção mais fácil e confiável.

Se você já se perguntou como essas plataformas e estruturas funcionam nos bastidores, você sempre pode ler as seções seguintes.

Plataformas de serviço#

If you’re developing for a “Platform-as-a-Service” or “PaaS”, you are going to want to follow their respective packaging guides. These types of platforms take care of packaging and deployment, as long as you follow their patterns. Most software does not fit one of these templates, hence the existence of all the other options below.

Se você estiver desenvolvendo um software que será implantado em suas máquinas, computadores pessoais de usuários ou qualquer outro arranjo, continue lendo.

Navegadores web e aplicações móveis#

Os avanços constantes do Python estão levando-o a novos espaços. Hoje em dia, você pode escrever uma aplicação móvel ou frontend de aplicação web no Python. Embora a linguagem possa ser familiar, as práticas de empacotamento e implantação são novas.

Se você está planejando lançar para essas novas fronteiras, convém verificar as seguintes estruturas e consultar seus guias de empacotamento:

Se você não está interessado em usar um framework ou plataforma, ou apenas quer saber sobre algumas das tecnologias e técnicas utilizadas pelos frameworks acima, continue lendo abaixo.

Dependendo de um Python pré-instalado#

Escolha um computador arbitrário e, dependendo do contexto, há uma boa chance do Python já estar instalado. Incluído por padrão na maioria dos sistemas operacionais Linux e Mac por muitos anos, você pode depender razoavelmente do Python preexistente em seus datacenters ou nas máquinas pessoais de desenvolvedores e cientistas de dados.

Tecnologias que oferecem suporte a este modelo:

  • PEX (Python EXecutable)

  • zipapp (não ajuda a gerenciar dependências, requer Python 3.5+)

  • shiv (requer Python 3)

Nota

De todas as abordagens aqui, depender de um Python pré-instalado depende mais do ambiente de destino. Claro, isso também contribui para o menor pacote, tão pequeno quanto megabytes de um dígito, ou mesmo kilobytes.

Em geral, diminuir a dependência do sistema de destino aumenta o tamanho do nosso pacote, portanto, as soluções aqui são organizadas de forma grosseira pelo aumento do tamanho da saída.

Dependendo de um ecossistema separado de distribuição de software#

Por um longo tempo, muitos sistemas operacionais, incluindo Mac e Windows, não tinham gerenciamento de pacotes integrado. Apenas recentemente esses sistemas operacionais ganharam as chamadas “app store”, mas mesmo aqueles se concentram em aplicações de consumo e oferecem pouco para os desenvolvedores.

Os desenvolvedores buscaram soluções por muito tempo e, nessa luta, surgiram com suas próprias soluções de gerenciamento de pacotes, como o Homebrew. A alternativa mais relevante para desenvolvedores Python é um ecossistema de pacotes chamado Anaconda. O Anaconda é construído em torno do Python e é cada vez mais comum em ambientes acadêmicos, analíticos e outros ambientes orientados a dados, chegando até a ambientes orientados a servidor <https://web.archive.org/web/20190403064038/https://www.paypal-engineering.com/2016/09/07/python-packaging-at-paypal/>`_.

Instruções sobre como construir e publicar para o ecossistema do Anaconda:

Um modelo semelhante envolve a instalação de uma distribuição alternativa Python, mas não oferece suporte a pacotes arbitrários em nível de sistema operacional:

Trazendo seu próprio executável Python#

A computação como a conhecemos é definida pela capacidade de executar programas. Cada sistema operacional oferece suporte nativamente a um ou mais formatos de programas que eles podem executar nativamente.

Existem muitas técnicas e tecnologias que transformam seu programa Python em um desses formatos, a maioria das quais envolve a incorporação do interpretador Python e quaisquer outras dependências em um único arquivo executável.

Essa abordagem, chamada congelamento, oferece ampla compatibilidade e experiência perfeita do usuário, embora muitas vezes exija múltiplas tecnologias e uma boa quantidade de esforço.

Uma seleção de congeladores Python:

A maioria dos itens acima implica em implantações de um único usuário. Para aplicações de servidor com vários componentes, consulte Chef Omnibus.

Trazendo seu próprio espaço de usuário#

Um número crescente de sistemas operacionais – incluindo Linux, Mac OS e Windows – pode ser configurado para executar aplicações empacotadas como imagens leves, usando um arranjo relativamente moderno, frequentemente referido como virtualização em nível de sistema operacional ou conteinerização.

Essas técnicas são principalmente Python agnósticas, porque empacotam sistemas de arquivos inteiros de sistemas operacionais, não apenas Python ou pacotes Python.

A adoção é mais extensa entre os servidores Linux, onde a tecnologia se originou e onde as tecnologias abaixo funcionam melhor:

Trazendo seu próprio kernel#

A maioria dos sistemas operacionais oferece suporte a alguma forma de virtualização clássica, executando aplicações empacotadas como imagens contendo um sistema operacional completo próprio. Executar essas máquinas virtuais, ou VMs, é uma abordagem madura, amplamente difundida em ambientes de datacenter.

Essas técnicas são reservadas principalmente para implantações em grande escala em datacenters, embora algumas aplicativas complexas possam se beneficiar desse pacote. As tecnologias são agnósticas ao Python e incluem:

Trazendo seu próprio hardware#

A maneira mais abrangente de enviar seu software seria enviá-lo já instalado em algum hardware. Dessa forma, o usuário do seu software precisaria apenas de eletricidade.

Considerando que as máquinas virtuais descritas acima são reservadas principalmente para os conhecedores de tecnologia, você pode encontrar dispositivos de hardware sendo usados por todos, desde os datacenters mais avançados até as crianças mais novas.

Incorpore seu código em um Adafruit, MicroPython ou hardware mais poderoso executando Python e, em seguida, envie-o para o datacenter ou para as casas de seus usuários. Eles conectam e estará funcionando, e você pode encerrar o dia.

Um resumo de tecnologias usadas para empacotar aplicações Python.

A gama simplificada de tecnologias usadas para empacotar aplicações Python.#

E quanto a…#

As seções acima resumem muito, e você pode estar se perguntando sobre algumas das lacunas mais evidentes.

Pacotes de sistema operacional#

Como mencionado em Dependendo de um ecossistema separado de distribuição de software acima, alguns sistemas operacionais possuem gerenciadores de pacotes próprios. Se você tiver certeza do sistema operacional que está almejando, pode depender diretamente de um formato como deb (para Debian, Ubuntu , etc.) ou RPM (para Red Hat, Fedora, etc.) e usar esse gerenciador de pacotes embutido para cuidar da instalação, e mesmo implantação. Você pode até usar FPM para gerar deb e RPMs da mesma fonte.

Na maioria das pipelines de implantação, o gerenciador de pacotes do sistema operacional é apenas uma peça do quebra-cabeça.

virtualenv#

Virtualenvs têm sido uma ferramenta indispensável para várias gerações de desenvolvedores Python, mas estão desaparecendo lentamente de vista, à medida que estão sendo envoltos por ferramentas de nível superior. Com o empacotamento em particular, virtualenvs são usados como primitivos na ferramenta dh-virtualenv e osnap, ambos envolvem virtualenvs de uma forma independente.

Para implantações de produção, não dependa da execução de python -m pip install da Internet em um virtualenv, como alguém pode fazer em um ambiente de desenvolvimento. A visão geral acima está repleta de soluções muito melhores.

Segurança#

Quanto mais fundo você descer nas camadas, mais difícil será para atualizar os componentes do seu pacote. Tudo está mais estreitamente ligado.

Por exemplo, se surgir um problema de segurança do kernel e você estiver implantando contêineres, o kernel do sistema host pode ser atualizado sem a necessidade de uma nova compilação em nome da aplicação. Se você implantar imagens de VM, precisará de uma nova construção. Se essa dinâmica torna ou não uma opção mais segura ainda é um debate antigo, voltando à questão ainda não resolvida de ligação estática versus ligação dinâmica.

Resumo#

O empacotamento no Python tem a reputação de ser um percurso acidentado. Essa impressão é principalmente um subproduto da versatilidade do Python. Depois de entender os limites naturais entre cada solução de empacotamento, você começa a perceber que o cenário variado é um preço pequeno Python que os programadores pagam por usar uma das linguagens mais equilibradas e flexíveis disponíveis.