Aprenda sobre como construir um pacote Python#
Depois que você tiver publicado ambas as distribuições do pacote (a distribuição de código-fonte e a wheel) no PyPI, você pode então publicar no conda-forge. O conda-forge requer uma distribuição de código-fonte no PyPI para construir o seu pacote no conda-forge. Você não precisa reconstruir o seu pacote para publicar no conda-forge.#
Você precisa construir o seu pacote Python para publicá-lo no PyPI (ou em um canal conda). O processo de build organiza o seu código e os metadados em um formato de distribuição que pode ser enviado ao PyPI e, posteriormente, baixado e instalado pelos usuários. NOTA: você precisa publicar um sdist no PyPI para que o conda-forge construa o seu pacote corretamente de forma automática.
O que é construir um pacote Python?#
Para publicar o seu pacote Python e facilitar a instalação para qualquer pessoa, você primeiro precisa construí-lo.
Mas o que significa construir um pacote Python?
Como mostrado na figura acima, quando você constrói o seu pacote Python, você converte os arquivos de código-fonte em algo chamado de pacote de distribuição. Um pacote de distribuição contém o seu código-fonte e metadados sobre o pacote, no formato exigido pelo Python Package Index, para que ele possa ser instalado por ferramentas como o pip.
Nota
O termo pacote costumava significar muitas coisas diferentes em Python e em outras linguagens. Nesta página, adotamos a convenção da Python Packaging Authority e nos referimos ao produto da etapa de build como um pacote de distribuição.
Esse processo de organizar e formatar o seu código, documentação, testes e metadados em um formato que tanto o pip quanto o PyPI possam usar é chamado de etapa de build.
Metadados do projeto e o PyPI#
Os metadados que tanto as ferramentas de build quanto o PyPI usam para descrever e entender o seu pacote geralmente são armazenados em um arquivo pyproject.toml. Esses metadados são usados para várias finalidades:
Eles ajudam qualquer ferramenta que você usar para construir o seu pacote (pip, o Build da pypa ou uma ferramenta de ponta a ponta como poetry, PDM ou Hatch) a entender como construir o seu pacote. As informações que eles fornecem à sua ferramenta de build incluem:
A tabela
[build-system]no seu arquivo pyproject.toml informa ao pip qual ferramenta de build backend você deseja usar para criar as suas distribuições sdist e wheel.
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
E a seção de dependências da sua tabela project informa à ferramenta de build e ao PyPI quais dependências o seu projeto requer.
dependencies = [
"dependency-package-name-1",
"dependency-package-name-2",
"pandas",
"xarray",
"geopandas",
"matplotlib"
]
Quando a ferramenta de build cria o arquivo de distribuição do seu pacote (o arquivo que você publica no PyPI), ela também cria um arquivo METADATA que o PyPI pode ler e usar para ajudar os usuários a encontrar o seu pacote. Por exemplo:
A seção
classifiers =da sua tabela[project]no arquivo pyproject.toml fornece informações que os usuários no PyPI podem usar para filtrar pacotes que abordam diferentes tópicos ou que dão suporte a versões específicas do python.
classifiers = [
# How mature is this project? Common values are
"Development Status :: 4 - Beta",
# Indicate who your project is intended for
"Intended Audience :: Developers",
"Topic :: Software Development :: Build Tools",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
]
O que aconteceu com o setup.py e o setup.cfg para metadados?
Os metadados do projeto costumavam ser armazenados em um arquivo setup.py ou em um arquivo setup.cfg. A prática recomendada atualmente para armazenar os metadados do pacote é usar um arquivo pyproject.toml. Saiba mais sobre o arquivo pyproject.toml aqui.
Um exemplo - xclim#
Quando você publica no PyPI, vai notar que cada pacote tem metadados listados. Vamos dar uma olhada no xclim, um dos nossos pacotes do pyOpenSci. Note que na página inicial do PyPI você vê alguns metadados sobre o pacote, incluindo python, informações do mantenedor e mais. O PyPI consegue preencher esses metadados porque eles foram definidos usando a sintaxe e os classifiers corretos pelos mantenedores do Xclim, arquivo pyproject.toml. Esses metadados, quando o pacote xclim é construído, são traduzidos em um arquivo de distribuição que permite ao PyPI ler os metadados e exibi-los no site deles.
Quando você adiciona a seção classifier ao seu pyproject.toml e o seu pacote é construído, a ferramenta de build organiza os metadados em um formato que o PyPI consegue entender e representar na página inicial do seu pacote no PyPI. Esses classifiers também permitem que os usuários filtrem os pacotes pela versão do python que eles suportam, categorias e mais.#
Você precisa construir o seu pacote Python para publicá-lo no PyPI (ou no Conda). O processo de build organiza o seu código e os metadados em um formato de distribuição que pode ser enviado ao PyPI e, posteriormente, baixado e instalado pelos usuários. NOTA: você precisa publicar um sdist no PyPI para que o conda-forge construa o seu pacote corretamente de forma automática.#
Captura de tela do PyPI mostrando os metadados para o pacote xclim.#
Nomes dos mantenedores e nomes de usuário do GitHub para o pacote xclim como são exibidos no PyPI. Essa informação é registrada no seu pyproject.toml e então processada pela sua ferramenta de build e armazenada nas distribuições sdist e wheel do seu pacote.#
Como criar o formato de distribuição que o PyPI e o Pip esperam?#
Em teoria, você poderia criar os seus próprios scripts para organizar o seu código da forma que o PyPI deseja. No entanto, assim como há pacotes que lidam com estruturas conhecidas, como o Pandas para data frames e o Numpy para arrays, há pacotes e ferramentas que ajudam você a criar os arquivos de distribuição de build do pacote.
Nota
Há um conjunto de ferramentas de packaging que podem ajudar você com todo o processo de packaging ou apenas com uma etapa do processo. Por exemplo, o setuptools é um back-end de build comumente usado que pode ser utilizado para criar o seu sdist e a sua wheel. Enquanto ferramentas como Hatch, PDM, Poetry e flit ajudam com outras partes do processo de packaging.
Embora isso possa causar alguma confusão e complexidade no ecossistema de packaging - na maioria das vezes, cada ferramenta fornece a mesma saída de distribuição (com pequenas diferenças com as quais a maioria dos usuários pode não se importar). Saiba mais sobre essas ferramentas nesta página.
Abaixo, você aprenderá sobre os dois arquivos de distribuição que o PyPI espera que você publique: sdist e wheel. Você aprenderá sobre a estrutura deles e quais arquivos pertencem a cada um.
Há dois arquivos de distribuição principais que você precisa criar para publicar o seu pacote Python no PyPI: a distribuição de código-fonte (frequentemente chamada de sdist) e a wheel. O sdist contém o código-fonte bruto do seu pacote. A wheel (.whl) contém os arquivos construídos / compilados que podem ser instalados diretamente no computador de qualquer pessoa.
Saiba mais sobre ambas as distribuições abaixo.
Nota
Se o seu pacote é um pacote Python puro sem etapas adicionais de build / compilação, então as distribuições sdist e wheel terão conteúdo semelhante. No entanto, se o seu pacote tem extensões em outras linguagens ou é mais complexo na sua build, as duas distribuições serão muito diferentes.
Observe também que não estamos discutindo fluxos de trabalho de build do conda nesta seção. Você pode aprender mais sobre builds do conda aqui.
O que é uma distribuição de código-fonte (sdist)#
Arquivos de código-fonte são os arquivos não construídos necessários para construir o seu pacote. Estes são os arquivos «brutos / como estão» que você armazena no GitHub ou em qualquer plataforma que você usa para gerenciar o seu código.
As Distribuições de Código-Fonte (S + Dist) são chamadas de sdist. Como o nome indica, um SDIST contém o código-fonte; ele não foi construído nem compilado de forma alguma. Assim, quando um usuário instala a sua distribuição de código-fonte usando o pip, o pip precisa executar uma etapa de build primeiro. Por esse motivo, você poderia definir uma distribuição de código-fonte como um arquivo compactado que contém tudo o que é necessário para construir uma wheel (exceto as dependências do projeto) sem acesso à rede.
O sdist normalmente é armazenado como um arquivo .tar.gz (frequentemente chamado de «tarball»). Assim, quando um usuário instala a sua distribuição de código-fonte usando o pip, o pip precisa executar uma etapa de build primeiro.
Abaixo está um exemplo de sdist para o pacote Python stravalib:
stravalib-1.1.0.post2-SDist.tar.gz file contents
├─ 📂 stravalib
│ ├─ tests
│ │ ├─ integration
│ │ │ ├─ __init__.py
│ │ │ ├─ conftest.py
│ │ │ ├─ strava_api_stub.py
│ │ │ └─ test_client.py
│ │ ├─ unit
│ │ │ ├─ __init__.py
│ │ │ ├─ test_attributes.py
│ │ │ ├─ ...
│ │ ├─ __init__.py
│ │ ├─ auth_responder.py
│ │ └─ test.ini-example
│ ├─ util
│ │ ├─ __init__.py
│ │ └─ limiter.py
│ ├─ __init__.py
│ ├─ _version.py
│ ├─ _version_generated.py
│ ├─ attributes.py
│ ├─ ...
├─ stravalib.egg-info
│ ├─ PKG-INFO
│ ├─ SOURCES.txt
│ ├─ dependency_links.txt
│ ├─ requires.txt
│ └─ top_level.txt
├─ CODE_OF_CONDUCT.md
├─ CONTRIBUTING.md
├─ LICENSE.txt
├─ MANIFEST.in
├─ Makefile
├─ PKG-INFO
├─ README.md
├─ CHANGELOG.md
├─ environment.yml
├─ pyproject.toml
├─ requirements-build.txt
├─ requirements.txt
└─ setup.cfg
Arquivo do GitHub vs sdist
Quando você faz um release no GitHub, ele cria um git archive que contém todos os arquivos do seu repositório do GitHub. Embora esses arquivos sejam semelhantes a um sdist, esses dois arquivos não são iguais. O sdist contém alguns outros itens, incluindo um diretório de metadados e, se você usar o setuptools_scm ou o hatch_vcs, o sdist também pode conter um arquivo que armazena a versão.
O que é uma wheel Python (whl):#
Um arquivo wheel é um arquivo em formato ZIP cujo nome segue um formato específico (abaixo) e tem a extensão .whl. O arquivo .whl contém um conjunto específico de arquivos, incluindo metadados gerados a partir do arquivo pyproject.toml do seu projeto. O pyproject.toml e outros arquivos que podem ser incluídos nas distribuições de código-fonte não são incluídos nas wheels porque ela é uma distribuição construída.
A wheel (.whl) é a sua distribuição binária construída. Arquivos binários são os arquivos de código-fonte construídos / compilados. Esses arquivos estão prontos para serem instalados. Uma wheel (.whl) é um arquivo zip que contém todos os arquivos necessários para instalar diretamente o seu pacote. Todos os arquivos em uma wheel são binários - isso significa que o código já está compilado / construído. As wheels são, portanto, mais rápidas de instalar - especialmente se você tem um pacote que requer etapas de build.
A wheel não contém nenhum dos arquivos de configuração do seu pacote, como o setup.cfg ou o pyproject.toml. Essa distribuição já está construída, então está pronta para instalar.
Por já estar construída, a wheel será mais rápida de instalar para projetos Python puros e pode levar a instalações consistentes entre máquinas.
Dica
As wheels também são úteis no caso de um pacote precisar de um arquivo setup.py para dar suporte a uma build mais complexa. Nesse caso, como os arquivos no pacote wheel são pré-construídos, o usuário que faz a instalação não precisa se preocupar com injeções de código malicioso durante a instalação.
O nome de arquivo de uma wheel contém metadados importantes sobre o seu pacote.
Exemplo: stravalib-1.1.0.post2-py3-none.whl
name: stravalib
version: 1.1.0
build-number: 2 (post2) (leia mais sobre post aqui)
py3: dá suporte ao Python 3.x
none: não é específica de sistema operacional (roda em windows, mac, linux)
any: roda em qualquer processador / arquitetura de computador
Como é um arquivo wheel quando descompactado (unzipped):
stravalib-1.1.0.post2-py3-none.whl file contents:
├─ 📂 stravalib
│ ├─ tests
│ │ ├─ functional
│ │ │ ├─ __init__.py
│ │ │ ├─ test_client.py
│ │ ├─ unit
│ │ │ ├─ __init__.py
│ │ │ ├─ test_attributes.py
│ │ ├─ __init__.py
│ │ ├─ auth_responder.py
│ │ └─ test.ini-example
│ ├─ util
│ │ ├─ __init__.py
│ │ └─ limiter.py
│ ├─ __init__.py
│ ├─ _version.py
│ ├─ _version_generated.py
│ ├─ attributes.py
│ ├─ client.py
└─ stravalib-1.1.0.post2.dist-info # Package metadata are stored here
├─ LICENSE.txt
├─ METADATA
├─ RECORD
├─ WHEEL
└─ top_level.txt