TLDR: Publicando no PyPI

Published on March 5, 2018

Já se perguntou como publicar seu próprio pacote Python para instalá-lo com o pip? É menos complicado que parece, e qualquer pessoa pode fazer.

Basta acessar o Python Package Index (PyPI) e criar uma conta na qual irá registrar seus pacotes.

Em seguida crie um arquivo python chamado setup.py alterando os valores que forem necessários:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from setuptools import find_packages, setup

setup(
    name='meu-pacote-python',
    packages=find_packages(),
    version='1.0.0',
    description='Descrição curta do meu pacote',
    long_description='Longa descrição do meu pacote',
    author='Meu Nome',
    author_email='meu@email.com',
    url='https://github.com/usuario/meu-pacote-python',
    install_requires=['dependencia1', 'dependencia2'],
    license="MIT",
    keywords=['dev', 'web'],
    classifiers=[
        'Intended Audience :: Developers',
        'License :: OSI Approved :: MIT License',
        'Natural Language :: English',
        'Programming Language :: Python :: 2',
        'Programming Language :: Python :: 3',
    ],
)

O find_packages é uma ferramenta muito boa para encontrar automaticamente os arquivos que fazem parte do seu pacote qualquer dúvida veja sua documentação clicando aqui.

Os classifiers servem para ajudar usuários a encontrar seu pacote na busca e a lista completa deles pode ser vista neste link.

Empacotando

Antes de publicar o pacote é preciso empacotá-lo e a forma mais simples é fazendo o empacotamento do código fonte rodando:

$ python setup.py sdist

Este modelo de empacotamento requer que o pip rode uma etapa de montagem após a instalação

Para já empacotar o código montado rode:

$ python setup.py bdist_wheel

Este comando empacota a versão montada para a versão do python em que você rodou o comando, para montar para python 2 e 3 rode duas vezes o comando (uma para cada versão do python)

Com isso você terá tudo empacotado e pronto para a publicação na pasta dist/.

Publicando

Para publicar é preciso instalar o twine que é uma ferramenta para publicar pacotes no PyPI:

$ pip install twine

Em seguida basta rodar o seguinte comando:

$ twine upload --username usuario-no-pypi dist/meu-pacote-1.0.0.tar.gz dist/meu-pacote-1.0.0-py2-none-any.whl dist/meu-pacote-1.0.0-py3-none-any.whl

O comando vai pedir a senha e em seguida fazer o upload para o PyPI.

Bônus - Versionamento

Uma prática muito comum é versionar o código e adicionar algumas informações no __init__.py desta forma:

__author__ = 'Meu Nome'
__email__ = 'meu@email.com'
__version__ = '1.0.0'

Adicione este código no setup.py para usar os dados do __init__.py no seu pacote:

import os
import re

package = 'meu_pacote'
init_py = open(os.path.join(package, '__init__.py')).read()
version = re.search(
    "^__version__ = ['\"]([^'\"]+)['\"]", init_py, re.MULTILINE).group(1)
author = re.search(
    "^__author__ = ['\"]([^'\"]+)['\"]", init_py, re.MULTILINE).group(1)
email = re.search(
        "^__email__ = ['\"]([^'\"]+)['\"]", init_py, re.MULTILINE).group(1)
...
setup(
    ...
    version=version,
    author=author,
    author_email=email,
    ...
)

Bônus - README.md para rst

Quem publica código no github costuma escrever o arquivo readme em markdown, mas a sintaxe de documentação do PyPI é em reStructured Text.

Para converter sua documentação para a publicação você pode usar o pacote pandoc.

$ pip install pypandoc

O pandoc precisa estar instalado no sistema para ser usado com pypandoc. Veja a documentação

Adicione este código no seu setup.py para realizar a conversão:

try:
    import pypandoc
    readme = pypandoc.convert('README.md', 'rst')
except (IOError, ImportError):
    readme = ''

setup(
    ...
    long_description=readme,
    ...
)

É importante colocar a conversão dentro do readme dentro de um bloco try ... except para não demandar a instalação do pypandoc nos usuários que vão usar o seu pacote.