Publicando Pacote no PyPI: Guia Completo
Aprenda a criar e publicar seu pacote Python no PyPI. Estrutura do projeto, setup, build, testes no TestPyPI e publicação final
Introdução
O PyPI (Python Package Index) é o repositório oficial de pacotes Python. Quando você executa pip install nome-do-pacote, o pip baixa o pacote diretamente do PyPI. Publicar seu próprio pacote permite que outros desenvolvedores reutilizem seu código facilmente.
Neste guia, vamos criar um pacote Python completo, testá-lo no TestPyPI e publicá-lo no PyPI oficial.
Pré-requisitos
- Python 3.10 ou superior
- Uma conta no pypi.org e no test.pypi.org
- Conhecimento básico de estrutura de projetos Python
Estrutura do projeto
Vamos criar um pacote simples chamado calculabr que formata números no padrão brasileiro:
calculabr/
src/
calculabr/
__init__.py
formatador.py
tests/
test_formatador.py
pyproject.toml
README.md
LICENSE
Crie as pastas:
mkdir -p calculabr/src/calculabr calculabr/tests
cd calculabr
Escrevendo o código do pacote
Crie src/calculabr/__init__.py:
from .formatador import formatar_real, formatar_cpf, formatar_cnpj
__version__ = "0.1.0"
Crie src/calculabr/formatador.py:
def formatar_real(valor: float) -> str:
"""Formata um valor numerico para o padrão monetário brasileiro.
Args:
valor: Valor numérico a ser formatado.
Returns:
String formatada no padrão R$ 1.234,56.
"""
if valor < 0:
return f"-R$ {abs(valor):,.2f}".replace(",", "X").replace(".", ",").replace("X", ".")
return f"R$ {valor:,.2f}".replace(",", "X").replace(".", ",").replace("X", ".")
def formatar_cpf(cpf: str) -> str:
"""Formata uma string de 11 digitos como CPF.
Args:
cpf: String contendo apenas os 11 digitos do CPF.
Returns:
CPF formatado no padrão 123.456.789-00.
"""
cpf = cpf.replace(".", "").replace("-", "")
if len(cpf) != 11:
raise ValueError("CPF deve conter 11 digitos")
return f"{cpf[:3]}.{cpf[3:6]}.{cpf[6:9]}-{cpf[9:]}"
def formatar_cnpj(cnpj: str) -> str:
"""Formata uma string de 14 digitos como CNPJ.
Args:
cnpj: String contendo apenas os 14 digitos do CNPJ.
Returns:
CNPJ formatado no padrão 12.345.678/0001-90.
"""
cnpj = cnpj.replace(".", "").replace("/", "").replace("-", "")
if len(cnpj) != 14:
raise ValueError("CNPJ deve conter 14 digitos")
return f"{cnpj[:2]}.{cnpj[2:5]}.{cnpj[5:8]}/{cnpj[8:12]}-{cnpj[12:]}"
Escrevendo testes
Crie tests/test_formatador.py:
from calculabr import formatar_real, formatar_cpf, formatar_cnpj
import pytest
def test_formatar_real_positivo():
assert formatar_real(1234.56) == "R$ 1.234,56"
def test_formatar_real_negativo():
assert formatar_real(-99.90) == "-R$ 99,90"
def test_formatar_cpf_valido():
assert formatar_cpf("12345678900") == "123.456.789-00"
def test_formatar_cpf_invalido():
with pytest.raises(ValueError):
formatar_cpf("123")
def test_formatar_cnpj_valido():
assert formatar_cnpj("12345678000190") == "12.345.678/0001-90"
Configurando o pyproject.toml
O pyproject.toml é o arquivo de configuração moderno para pacotes Python. Crie-o na raiz do projeto:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "calculabr"
version = "0.1.0"
authors = [
{ name = "Seu Nome", email = "seu@email.com" },
]
description = "Formatador de valores no padrao brasileiro"
readme = "README.md"
requires-python = ">=3.10"
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Natural Language :: Portuguese (Brazilian)",
]
[project.urls]
Homepage = "https://github.com/seu-usuario/calculabr"
Issues = "https://github.com/seu-usuario/calculabr/issues"
Os campos mais importantes são name (que deve ser único no PyPI), version e requires-python.
Criando o README.md
O README aparece na página do pacote no PyPI:
# calculabr
Formatador de valores no padrao brasileiro para Python.
## Instalacao
pip install calculabr
## Uso
from calculabr import formatar_real, formatar_cpf
print(formatar_real(1234.56)) # R$ 1.234,56
print(formatar_cpf("12345678900")) # 123.456.789-00
Criando a licença
Para projetos de código aberto, a licença MIT é a mais comum. Crie o arquivo LICENSE com o texto padrão da MIT License, substituindo ano e nome.
Gerando o pacote
Instale as ferramentas de build:
pip install build twine
Gere os arquivos de distribuição:
python -m build
Isso cria dois arquivos na pasta dist/:
calculabr-0.1.0.tar.gz(source distribution)calculabr-0.1.0-py3-none-any.whl(wheel / distribuição binária)
Testando no TestPyPI
Antes de publicar no PyPI oficial, teste no TestPyPI:
python -m twine upload --repository testpypi dist/*
O twine vai pedir suas credenciais do TestPyPI. Para usar tokens de API (recomendado):
python -m twine upload --repository testpypi dist/* -u __token__ -p pypi-SeuTokenAqui
Teste a instalação:
pip install --index-url https://test.pypi.org/simple/ calculabr
Verifique se funciona:
from calculabr import formatar_real
print(formatar_real(9999.99)) # R$ 9.999,99
Publicando no PyPI oficial
Se tudo funcionou no TestPyPI, publique no PyPI real:
python -m twine upload dist/*
Pronto! Seu pacote estará disponível em https://pypi.org/project/calculabr/ e qualquer pessoa poderá instalá-lo com:
pip install calculabr
Configurando tokens de API
Para não precisar digitar credenciais toda vez, crie o arquivo ~/.pypirc:
[pypi]
username = __token__
password = pypi-SeuTokenPyPI
[testpypi]
repository = https://test.pypi.org/legacy/
username = __token__
password = pypi-SeuTokenTestPyPI
Gere tokens em Account Settings > API Tokens no site do PyPI.
Atualizando o pacote
Para publicar uma nova versão:
- Atualize a versão no
pyproject.tomle__init__.py - Remova a pasta
dist/antiga:rm -rf dist/ - Gere novamente:
python -m build - Publique:
python -m twine upload dist/*
Siga o versionamento semântico: MAJOR.MINOR.PATCH (ex: 1.0.0 para a primeira versão estável).
Boas práticas
- Escolha nomes descritivos e únicos para seus pacotes
- Sempre inclua testes automatizados
- Documente funções com docstrings
- Use type hints para melhorar a experiência do usuário
- Teste no TestPyPI antes de publicar oficialmente
- Configure CI/CD para automatizar publicação com GitHub Actions
Conclusão
Publicar um pacote no PyPI é mais simples do que parece. Com o pyproject.toml, ferramentas de build modernas e o TestPyPI para testes, o processo é seguro e direto. Compartilhar código como pacote é uma excelente forma de contribuir com a comunidade Python e facilitar a reutilização de soluções em diferentes projetos.