
Passo 1 de 8
Identificar o papel do pyproject.toml
Reconheça o que o pyproject.toml configura e o que continua sendo responsabilidade da configuração usada pela aplicação.
Trilha de aprendizado · Nível 15 · Tutorial 6
Preparar o projeto para instalação, declarando seus metadados, dependências e comando de terminal em pyproject.toml.
Identificar o papel do pyproject.toml
Reconheça o que o pyproject.toml configura e o que continua sendo responsabilidade da configuração usada pela aplicação. 2 min
Organizar o código no layout src
Crie uma estrutura local em que o pacote importável fica em src/tarefas, separado dos arquivos de configuração e documentação da raiz. 3 min
Configurar o backend e a descoberta de pacotes
Configure o setuptools para construir o projeto e localizar o pacote tarefas dentro de src. 3 min
Declarar identidade e compatibilidade
Defina metadados estáticos da distribuição, conecte o README existente e declare uma versão mínima de Python coerente com o uso de tomllib. 3 min
Separar dependências de execução e desenvolvimento
Classifique requisitos do projeto para declarar somente o necessário em cada parte do pyproject.toml. 4 min
Registrar as duas formas de iniciar a CLI
Configure o comando instalável e a execução com python -m para que ambos usem a mesma função main. 4 min
Verificar a instalação editável
Instale o projeto em modo editável e confira as duas formas de iniciar a CLI durante o desenvolvimento. 4 min
Revisar a configuração como um conjunto
Revise as relações entre a árvore de arquivos, o pyproject.toml e as entradas da CLI antes de avançar para a geração de distribuições. 3 min

Passo 1 de 8
Reconheça o que o pyproject.toml configura e o que continua sendo responsabilidade da configuração usada pela aplicação.
O pyproject.toml fica na raiz do projeto. Ele é o ponto central para declarar como a distribuição Python será construída, qual é sua identidade e quais ferramentas podem ter configurações próprias.
Ele descreve o projeto para ferramentas do ecossistema Python; não é, por si só, o arquivo de preferências que sua aplicação lê ao executar.
Compare a configuração da distribuição com a configuração de uso da CLI.

pyproject.toml orienta o ecossistema de empacotamento; a CLI pode ler outro arquivo para obter suas preferências.
Dica
Pergunte: “isto informa como o projeto é distribuído ou é uma preferência para a aplicação rodar?”. No primeiro caso, tende a pertencer ao pyproject.toml; no segundo, tende a pertencer ao arquivo de configuração da aplicação.
Sem preencher opções ainda, pense nas tabelas mais comuns assim:
As tabelas organizam responsabilidades diferentes no mesmo arquivo.
Exemplo
[build-system]
# Como a distribuição será construída
[project]
# Identidade e requisitos da distribuição
[tool.alguuma-ferramenta]
# Preferências desta ferramentaNeste momento, o objetivo é reconhecer o papel de cada área. Os campos concretos serão adicionados nos próximos passos.
No projeto contínuo deste tutorial, os três nomes abaixo se referem a papéis distintos, embora dois deles tenham o mesmo texto:
import tarefas.tarefas.O nome da distribuição não precisa ser igual ao nome do pacote importável nem ao do comando.
O mesmo projeto pode expor uma identidade de distribuição e interfaces de uso diferentes.

Distribuição, pacote e comando se relacionam, mas são identificadores com funções diferentes.
Relacione cada informação ao local que normalmente deve recebê-la neste projeto.
Toque em um item e depois no par correspondente.

Passo 2 de 8
Crie uma estrutura local em que o pacote importável fica em src/tarefas, separado dos arquivos de configuração e documentação da raiz.
No layout src, o código que será importado fica dentro de src/tarefas. Já os arquivos do projeto, como pyproject.toml, README.md e testes, permanecem na raiz.
Para este exemplo, crie uma pasta de projeto chamada tarefas-cli no seu computador. O nome da distribuição poderá ser tarefas-cli, enquanto o pacote importável será tarefas.
A árvore abaixo mostra a separação entre a raiz do projeto e o pacote Python.

Somente tarefas, dentro de src, é o pacote importável.
Dica
Evite manter outra pasta tarefas/ ao lado de src/. Duas cópias do mesmo pacote tornam fácil executar um código diferente daquele que você pretende distribuir.
No editor, crie src/tarefas/__init__.py vazio. Em seguida, crie src/tarefas/cli.py com o conteúdo completo abaixo.
A CLI usa somente a biblioteca padrão. O import de tomllib será útil para manter a compatibilidade do projeto coerente com Python 3.11 ou superior em uma etapa posterior.
import argparse
import tomllib
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(
prog="tarefas",
description="Lista tarefas de exemplo.",
)
parser.add_argument(
"--config",
default="config.toml",
help="caminho do arquivo de configuração",
)
args = parser.parse_args(argv)
print(f"Configuração selecionada: {args.config}")
print("Nenhuma tarefa pendente.")
return 0
if __name__ == "__main__":
raise SystemExit(main())Atenção
Neste momento, não use python -m tarefas: o arquivo __main__.py e a instalação do projeto serão tratados depois. Por enquanto, o objetivo é deixar os arquivos no lugar certo.
O diretório src não entra no nome das importações. Quando o pacote estiver configurado e instalado, o uso será import tarefas, nunca import src.tarefas.
Como a raiz do projeto não contém diretamente a pasta tarefas, executar Python nela não deve fazer o pacote aparecer por acidente. Isso obriga o desenvolvimento a usar a instalação configurada, em vez de confundir as fontes locais com o pacote instalado.
Qual árvore representa o layout src para um pacote importável chamado tarefas?

Passo 3 de 8
Configure o setuptools para construir o projeto e localizar o pacote tarefas dentro de src.
O backend é o componente que lê a configuração e prepara a distribuição do projeto. Neste exemplo, usaremos o setuptools.
A tabela [build-system] declara:
requires: o que é necessário para executar o backend durante a construção;build-backend: o objeto Python que será usado como backend.Esses requisitos são de construção. Eles não descrevem bibliotecas exigidas para a CLI tarefas funcionar quando estiver instalada.
Adicione esta tabela ao pyproject.toml na raiz do projeto.
[build-system]
requires = ["setuptools>=64"]
build-backend = "setuptools.build_meta"Sua árvore contém o pacote regular tarefas dentro de src:
projeto/
├── pyproject.toml
├── README.md
└── src/
└── tarefas/
├── __init__.py
└── cli.pyO nome importável continua sendo tarefas, e não src.tarefas. Por isso, o setuptools precisa receber duas informações explícitas: src é a raiz dos pacotes e é ali que deve procurar pacotes.
A configuração aponta para src; a descoberta encontra tarefas porque ele possui __init__.py.

package-dir e where direcionam o setuptools para a pasta que contém os pacotes importáveis.
Acrescente estas tabelas ao mesmo pyproject.toml, após [build-system].
[tool.setuptools]
package-dir = {"" = "src"}
[tool.setuptools.packages.find]
where = ["src"]
namespaces = falseDica
Este projeto usa pacotes regulares, identificados por __init__.py, como src/tarefas/__init__.py. Com namespaces = false, a descoberta fica alinhada a essa estrutura e não procura pacotes de namespace neste exemplo.
Para localizar o pacote tarefas na árvore src/tarefas/__init__.py, complete:
where = ["____"]

Passo 4 de 8
Defina metadados estáticos da distribuição, conecte o README existente e declare uma versão mínima de Python coerente com o uso de tomllib.
No pyproject.toml, a tabela [project] descreve a distribuição que será instalada. Comece com valores estáticos para name, version e description.
Para este projeto, a distribuição se chama tarefas-cli, enquanto o pacote que será importado continua sendo tarefas. Esses nomes podem coincidir, mas não precisam ser iguais. A version é uma string em TOML.

name identifica a distribuição; o nome do pacote é usado nos imports.
Adicione ou complete esta tabela no seu pyproject.toml:
[project]
name = "tarefas-cli"
version = "0.1.0"
description = "Gerenciador de tarefas pela linha de comando"O campo readme aponta para um arquivo relativo ao diretório que contém o pyproject.toml. Portanto, ao usar readme = "README.md", crie esse arquivo na raiz do projeto.
Já requires-python informa o requisito de instalação da distribuição. Como a CLI de referência usa tomllib, disponível na biblioteca padrão a partir do Python 3.11, declare ">=3.11".
Acrescente estas duas linhas à tabela [project]:
readme = "README.md"
requires-python = ">=3.11"No mesmo diretório do pyproject.toml, crie o arquivo README.md com este conteúdo mínimo:
# tarefas-cli
Aplicação de linha de comando para gerenciar tarefas.Atenção
requires-python = ">=3.11" impede a instalação em versões anteriores incompatíveis. Ele não instala o Python 3.11 e não prova que todas as versões aceitas foram testadas.
Qual alternativa está coerente com uma CLI que usa tomllib e possui um arquivo README.md na raiz do projeto?

Passo 5 de 8
Classifique requisitos do projeto para declarar somente o necessário em cada parte do pyproject.toml.
Em [project], dependencies lista bibliotecas de terceiros necessárias quando alguém usa a aplicação normalmente. Ela não é uma lista de tudo que existe no ambiente de desenvolvimento.
A CLI tarefas deste exemplo usa apenas a biblioteca padrão, inclusive tomllib. Por isso, sua lista de dependências de execução pode ficar vazia: dependencies = [].

Uma biblioteca usada pela aplicação entra em dependencies; ferramentas usadas para verificar o projeto podem formar o extra dev. A biblioteca padrão não entra em nenhuma dessas listas.
Dica
Pergunte: “Se uma pessoa instalar a distribuição apenas para executar a aplicação, esta biblioteca será necessária?” Se sim, ela pertence a dependencies, mesmo que também seja útil durante o desenvolvimento.
Adicione estas tabelas ao pyproject.toml já iniciado nos passos anteriores.
[project]
name = "tarefas-cli"
version = "0.1.0"
description = "Uma CLI simples para tarefas"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
[project.optional-dependencies]
dev = [
"pytest>=8",
"ruff>=0.6",
"mypy>=1.10",
]Exemplo
Se a CLI passasse a usar uma biblioteca externa chamada httpx para fazer requisições durante sua operação normal, a declaração passaria a incluir, por exemplo:
dependencies = ["httpx>=0.27"]
O limite >=0.27 expressa a versão mínima compatível exigida pelo código. Ele deve ser justificado pelo que a aplicação usa — não copiado automaticamente das versões instaladas na sua máquina.
Atenção
Uma biblioteca necessária para executar um comando da aplicação não pode ficar somente em dev. Quem instalar a distribuição sem ferramentas de desenvolvimento teria uma falha em tempo de execução.
A saída de pip freeze é um inventário congelado do ambiente atual: pode incluir dependências transitivas, ferramentas usadas em outros projetos e versões fixadas por motivos locais. Já dependencies descreve os requisitos diretos da distribuição.
Mantenha no pyproject.toml apenas o que o projeto declara precisar. Os extras, como dev, são conjuntos opcionais adicionais para tarefas de desenvolvimento; eles não tornam pytest, Ruff e mypy requisitos de uso normal.
Copiar toda a saída de pip freeze para dependencies é uma forma adequada de declarar os requisitos da distribuição.
Associe cada item ao local ou tratamento mais adequado no projeto tarefas.
Toque em um item e depois no par correspondente.

Passo 6 de 8
Configure o comando instalável e a execução com python -m para que ambos usem a mesma função main.
A distribuição terá duas formas de iniciar a mesma interface:
tarefas;python -m tarefas.As duas devem delegar para tarefas.cli:main. Assim, a interpretação dos argumentos, as regras da aplicação e os códigos de saída permanecem em um único lugar.
Os dois caminhos chegam à mesma função de entrada.

Evite criar uma implementação diferente para cada forma de iniciar a CLI.
No pyproject.toml, acrescente a tabela abaixo. O lado esquerdo é o nome que o usuário digitará no terminal; o lado direito é uma referência no formato módulo:função.
A referência não é um caminho de arquivo: não use src/tarefas/cli.py. Também não é uma chamada: não use parênteses em main().
Acrescente esta tabela ao arquivo, no mesmo nível de [project].
[project.scripts]
tarefas = "tarefas.cli:main"Dica
O instalador criará um comando que chama main() sem argumentos obrigatórios. Portanto, mantenha o parâmetro opcional já adotado pela CLI, como def main(argv: list[str] | None = None) -> int:. O inteiro retornado por main será encaminhado como código de saída do processo.
Crie o arquivo src/tarefas/__main__.py. Ao executar python -m tarefas, o Python executará esse módulo. Ele apenas importa e chama a main existente, preservando o retorno inteiro com SystemExit.
Este arquivo não deve repetir o parser nem as regras da aplicação.
from .cli import main
if __name__ == "__main__":
raise SystemExit(main())Exemplo
src/tarefas/cli.py continua sendo o local de main(argv=None) e da implementação da CLI. Já src/tarefas/__main__.py é uma ponte curta para a execução por módulo. O comando declarado em [project.scripts] também aponta diretamente para essa mesma main.
Complete o valor da configuração:
tarefas = "____"
Complete a linha final de src/tarefas/__main__.py:
raise ____(main())

Passo 7 de 8
Instale o projeto em modo editável e confira as duas formas de iniciar a CLI durante o desenvolvimento.
Na raiz do projeto, confira se os arquivos referenciados existem e se o pacote está dentro de src. O nome da distribuição é tarefas-cli; o pacote importável e o comando continuam sendo tarefas.
tarefas-cli/
├── pyproject.toml
├── README.md
├── src/
│ └── tarefas/
│ ├── __init__.py
│ ├── __main__.py
│ └── cli.py
└── tests/ # opcional neste momentoAntes de instalar, salve este conteúdo como pyproject.toml na raiz do projeto.
[build-system]
requires = ["setuptools>=64"]
build-backend = "setuptools.build_meta"
[project]
name = "tarefas-cli"
version = "0.1.0"
description = "Uma CLI simples para organizar tarefas"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
[project.optional-dependencies]
dev = [
"pytest>=8",
"ruff>=0.6",
"mypy>=1.11",
]
[project.scripts]
tarefas = "tarefas.cli:main"
[tool.setuptools]
package-dir = {"" = "src"}
[tool.setuptools.packages.find]
where = ["src"]
namespaces = false
A configuração aponta para o pacote em src; a instalação cria a forma de chamar sua função de entrada pelo terminal.
Com o ambiente virtual de desenvolvimento ativado e o terminal aberto na pasta que contém pyproject.toml, use o pip associado ao mesmo Python.
python -m pip install -e .Dica
Para instalar também o extra dev, use o comando abaixo. Ele adiciona pytest, Ruff e mypy ao ambiente, mas esses pacotes não são necessários para alguém usar normalmente a CLI.
python -m pip install -e ".[dev]"Primeiro, compare as ajudas. Elas devem expor as mesmas opções e subcomandos, pois tanto o comando instalado quanto python -m tarefas delegam para tarefas.cli:main. A linha de uso pode mostrar o nome usado para iniciar cada uma.
Depois da ajuda, execute uma operação simples já disponível na sua CLI — por exemplo, listar tarefas. O resultado funcional e o código de saída devem ser equivalentes nas duas entradas.
tarefas --help
python -m tarefas --help
# Exemplo de operação que não altera dados:
tarefas listar
python -m tarefas listar
Não duplique o tratamento de argumentos: as duas entradas devem alcançar a mesma função main.
Atenção
A ajuda confirma que a entrada foi encontrada e que o parser iniciou. Execute também uma operação simples da sua aplicação para observar que as duas entradas chegam às mesmas regras e ao mesmo armazenamento configurado.
Faça uma alteração pequena em src/tarefas/cli.py, como ajustar a descrição passada ao ArgumentParser. Salve o arquivo e execute novamente tarefas --help; a nova descrição deve aparecer sem rodar outra vez a instalação. O ambiente editável está vinculado às fontes do projeto.
Atenção
Repita python -m pip install -e . após mudar metadados, dependências ou pontos de entrada no pyproject.toml. Alterações apenas em arquivos Python existentes normalmente são percebidas na próxima execução.
Relate sua verificação: qual comando instalou o projeto, como as duas entradas se comportaram, qual alteração de código você observou sem reinstalar e por que isso ainda não valida uma distribuição final.
Escreva pelo menos 180 caracteres (0/180).

Passo 8 de 8
Revise as relações entre a árvore de arquivos, o pyproject.toml e as entradas da CLI antes de avançar para a geração de distribuições.
Antes de considerar o projeto pronto para distribuição, confira se cada declaração no pyproject.toml corresponde a algo real no projeto. A revisão cruza quatro pontos: a árvore em src/, a descoberta de pacotes, os arquivos citados pelos metadados e o destino do comando de terminal.
Use este fluxo para localizar incoerências: os arquivos devem sustentar as referências declaradas.

Cada referência da configuração precisa apontar para um arquivo, pacote ou função que exista.
Dica
Comece pelos arquivos existentes; depois confira os caminhos e nomes no TOML; por fim, execute as duas entradas da CLI após a instalação editável. Isso evita diagnosticar um comando quando o pacote ainda não foi encontrado.
Considere esta árvore, criada no diretório atual:
.
├── README.md
├── pyproject.toml
└── src/
└── tarefas/
├── __init__.py
├── __main__.py
└── cli.pyA CLI usa tomllib. Não há bibliotecas de terceiros necessárias durante a execução.
Compare cada trecho com a árvore e com o comportamento esperado.
[build-system]
requires = ["setuptools>=64"]
build-backend = "setuptools.build_meta"
[project]
name = "tarefas-cli"
version = "0.1.0"
description = "Uma CLI para tarefas"
readme = "LEIA-ME.md"
requires-python = ">=3.10"
dependencies = ["tomllib"]
[project.optional-dependencies]
dev = ["pytest", "ruff", "mypy"]
[project.scripts]
tarefas = "tarefas.main:main"
[tool.setuptools]
package-dir = {"" = "src"}
[tool.setuptools.packages.find]
where = ["pacotes"]
namespaces = falseListe as correções necessárias no arquivo mostrado. Inclua o caminho do README, a versão mínima de Python, a lista de dependências, o destino do comando e o diretório de descoberta.
Escreva pelo menos 120 caracteres (0/120).
Resumo
Uma correção coerente alinha todas as referências ao projeto observado.
readme = "README.md", pois o arquivo existe na raiz.requires-python = ">=3.11", pois a CLI usa tomllib.dependencies = []: biblioteca padrão não é dependência de terceiros.tarefas = "tarefas.cli:main": módulo e função existem nesse destino.where = ["src"]: a descoberta parte do diretório que contém o pacote tarefas.setuptools é requisito de construção; pytest, Ruff e mypy são ferramentas opcionais de desenvolvimento.Ao executar python -m pip install -e . e testar tarefas --help e python -m tarefas --help, você verificou que as fontes atuais podem ser usadas pelo ambiente de desenvolvimento e que as duas entradas alcançam a mesma CLI. Mudanças em código Python podem aparecer em uma nova execução sem reinstalar.
Por outro lado, isso não comprova que uma distribuição final conterá todos os arquivos necessários. Essa validação será feita na próxima etapa, ao gerar e inspecionar os artefatos.
Resumo
Antes de seguir, confirme estes pontos no seu projeto.
src/tarefas/, com __init__.py.package-dir e where apontam para src.dev.tarefas.cli:main, e __main__.py delega para a mesma função.Parabéns! Você concluiu: Configurar uma distribuição com pyproject.toml
Milhares de cursos online em vídeo, ebooks e áudiobooks.
Para testar seus conhecimentos no decorrer dos cursos online
Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail
Baixe nosso aplicativo pelo QR Code ou pelos links abaixo:.
+ de 10 milhões
de alunos
Certificado grátis e
válido em todo o Brasil
60 mil exercícios
gratuitos
4,8/5 classificação
nas lojas de apps
Cursos gratuitos em
vídeo, ebooks e audiobooks