Empacotando e distribuindo
LidoEsta aula aborda o empacotamento e distribuição de projetos Python, incluindo a configuração via pyproject.toml, o processo de build, a publicação no PyPI e boas práticas de versionamento. O aluno aprenderá a criar pacotes instaláveis e a publicá-los para a comunidade.
Nesta aula, você vai aprender a empacotar e distribuir seus projetos Python, transformando seu código em um pacote instalável que pode ser compartilhado com outras pessoas ou publicado no PyPI (Python Package Index). Esse processo é essencial para distribuir bibliotecas, ferramentas de linha de comando ou aplicações que precisam ser instaladas em outros ambientes.
Vamos explorar o arquivo pyproject.toml, que se tornou o padrão para configuração de pacotes, o processo de build com ferramentas como build e setuptools, uma visão geral da publicação no PyPI e as boas práticas de versionamento semântico. Ao final, você terá uma base sólida para publicar seus próprios pacotes.
pyproject.toml
O pyproject.toml é o arquivo de configuração central para empacotamento em Python moderno. Ele foi introduzido pela PEP 518 (2016) e se tornou obrigatório a partir da PEP 621 (2020) para definir metadados de pacotes. Ele substitui o antigo setup.py e setup.cfg em muitos aspectos, permitindo uma configuração declarativa e mais limpa.
Um pyproject.toml típico contém seções como [build-system], que especifica a ferramenta de build, e [project], que define os metadados do pacote (nome, versão, descrição, dependências, etc.). Veja um exemplo básico:
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
[project]
name = "meu-pacote"
version = "0.1.0"
description = "Um pacote de exemplo"
readme = "README.md"
authors = [
{name = "Seu Nome", email = "seu@email.com"}
]
license = {text = "MIT"}
requires-python = ">=3.8"
dependencies = [
"requests>=2.25"
]
[tool.setuptools.packages.find]
include = ["meupacote*"]
A seção [build-system] indica que usaremos o setuptools como backend. O campo requires é usado pelo pip para preparar o ambiente de build. A seção [project] contém os metadados: nome, versão, descrição, autores, licença, versão mínima do Python e dependências. Para incluir pacotes, usamos [tool.setuptools.packages.find] para localizar automaticamente os pacotes no diretório. Outras ferramentas, como Poetry e Flit, também usam pyproject.toml, mas com formatos diferentes.
build
O processo de build transforma seu código-fonte em artefatos distribuíveis, como wheels (pacotes .whl) e source distributions (sdist, .tar.gz). O wheel é um formato binário que acelera a instalação, enquanto o sdist contém o código-fonte e pode ser usado para builds em outras plataformas.
Para construir seu pacote, você pode usar a ferramenta build, que é a recomendação oficial. Primeiro, instale-a com pip install build. Em seguida, execute python -m build no diretório raiz do projeto. Isso criará uma pasta dist/ com os artefatos. Alternativamente, você pode usar pip wheel . -w dist para gerar apenas o wheel, ou python setup.py sdist se estiver usando setuptools, mas o build é mais simples e moderno.
$ pip install build
$ python -m build
O comando acima gera os arquivos em dist/. Você pode inspecionar o conteúdo do wheel com unzip -l dist/meu_pacote-0.1.0-py3-none-any.whl. O wheel é um zip com uma estrutura específica. Para testar o pacote localmente, você pode instalá-lo com pip install dist/meu_pacote-0.1.0-py3-none-any.whl.
Publicando no PyPI (visão geral)
PyPI (Python Package Index) é o repositório oficial de pacotes Python. Publicar seu pacote lá permite que qualquer pessoa instale com pip install seu-pacote. O processo envolve criar uma conta no PyPI, gerar um token de API e usar uma ferramenta como twine para enviar os artefatos.
Para publicar, primeiro crie uma conta em pypi.org e ative a autenticação de dois fatores. Depois, crie um token de API em pypi.org/manage/account/token/. Em seguida, instale o twine: pip install twine. Antes de publicar, é recomendável testar no TestPyPI, um ambiente de testes. O comando para enviar é:
$ twine upload dist/*
Você será solicitado a fornecer o token como nome de usuário e __token__ como senha (ou use a variável de ambiente TWINE_PASSWORD). Para o TestPyPI, use --repository testpypi. Após o upload, seu pacote estará disponível publicamente. Lembre-se de que a versão deve ser única; você não pode republicar a mesma versão.
Versionamento
O versionamento é crucial para comunicar mudanças e garantir compatibilidade. O esquema mais comum é o Versionamento Semântico (SemVer), que usa o formato MAJOR.MINOR.PATCH. Incremente MAJOR para mudanças que quebram compatibilidade, MINOR para novas funcionalidades retrocompatíveis e PATCH para correções de bugs.
Além disso, é comum usar sufixos como alpha, beta, rc para pré-lançamentos (ex.: 1.0.0rc1). No pyproject.toml, a versão é definida no campo version. Você também pode usar ferramentas como setuptools-scm para gerar automaticamente a versão a partir de tags do git, evitando duplicação. Exemplo de configuração:
[project]
name = "meu-pacote"
dynamic = ["version"]
[tool.setuptools_scm]
version_scheme = "guess-next-dev"
Com essa configuração, a versão é derivada do git. Sempre que fizer uma alteração, use git tag v0.1.0 e o build usará essa versão. Isso reduz erros manuais de versionamento.
Boas práticas e observações finais
- Use
pyproject.tomlpara todos os projetos novos, mesmo que simples. - Inclua um
README.mdcom instruções de uso e instalação. - Defina uma licença clara (ex.: MIT, Apache 2.0).
- Teste seu pacote em um ambiente limpo (ex.: via
pip install .em um virtualenv). - Publique no TestPyPI antes do PyPI oficial para validar o processo.
- Mantenha o versionamento semântico e documente as mudanças em um changelog.
Referências
- Packaging Python Projects - Documentação oficial
- PEP 518 – Specifying Minimum Build System Requirements
- PEP 621 – Storing project metadata in pyproject.toml
- Semantic Versioning 2.0.0
- PyPI - Python Package Index
- build - PyPI
- twine - PyPI
- Setuptools - Pyproject config
Exercícios
- Crie um arquivo
pyproject.tomlpara um pacote chamadocalculadoracom versão 1.0.0, descrição curta, autor, licença MIT e dependência denumpy. - Instale a ferramenta
builde gere os artefatos de distribuição (sdist e wheel) para o pacote do exercício anterior. Liste os arquivos gerados. - Explique a diferença entre sdist e wheel e quando usar cada um.
- Qual é o comando para enviar seu pacote para o PyPI usando twine? Escreva o comando completo, incluindo a autenticação via variável de ambiente para o token.
- Usando versionamento semântico, qual seria a próxima versão para cada cenário: (a) correção de bug, (b) nova funcionalidade retrocompatível, (c) mudança que quebra a API?
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
[project]
name = "calculadora"
version = "1.0.0"
description = "Uma calculadora simples"
authors = [{name = "Seu Nome", email = "seu@email.com"}]
license = {text = "MIT"}
requires-python = ">=3.8"
dependencies = ["numpy"]
pip install build e depois python -m build. Isso criará a pasta dist/ com os arquivos calculadora-1.0.0-py3-none-any.whl e calculadora-1.0.0.tar.gz.export TWINE_USERNAME=__token__
export TWINE_PASSWORD=seu_token_aqui
twine upload dist/*