Empaquetar un programa #Python i pujar-lo a PyPi

Ja tenim acabat i funcionant a plena satisfacció el nostre programa #Python i ens agradaria compartir-lo a PyPi, l'index universal de paquets Python. Tenir-lo allà permet que qualsevol persona que el vulgui instal·lar en el seu ordinador o servidor només li caldrà fer el famós pip install nom_del_paquet.

Estructura

El que cal fer és tenir tots els fitxers necessaris per a executar-lo dins d'un sub directori. Com a exemple utilitzaré el cas real del meu Python wrapper for Akkoma API.

.
├── akkoma
│   ├── Akkoma.py
│   ├── __init__.py
├── LICENSE
├── README.md
├── setup.py
├── tests  

En el sub directori akkoma hi hem de tenir tant el codi que hem programat (el fitxer Akkoma.py) com __init__.py, que serveix per a que Python tracti aquest sub directori com un contenidor de paquets si __init__.py és un arxiu buid o aprofitar-lo per a inicialitzar el nostre programa. Per a no fer massa complexe aquesta entrada recomano llegir aquest enllaç per a entendre millor aquests conceptes.
Hi tenim un altre sub directori, test, que per ara el podem deixar buit. En l'arrel del projecte cal tenir la llicència que li vulguem posar (LICENSE), el inevitable README.md on expliquem com funciona el nostre programa i setup.py, molt important perquè descriu el paquet, diu a setuptools com construir-lo, com pujar-lo a PyPi i què es mostrarà allà.

setup.py

El rovell de l'ou. Aquest és el setup.py real que he utilitzat:

import setuptools

VERSION = '0.1.6'

with open('README.md', 'r', encoding='utf-8') as fh:
    long_description = fh.read()

setuptools.setup(
    name='Akkoma.py',
    version=VERSION,
    author='el_nostre_usuari_a_PyPi',
    author_email='adreça@correu.cat',
    description='Python wrapper for the [Akkoma](https://akkoma.dev/AkkomaGang/akkoma) API.',
    packages=['akkoma'],
    long_description=long_description,
    long_description_content_type='text/markdown',
    url='https://git.mastodont.cat/spla/Akkoma.py',
    install_requires=['pytz', 'requests', 'python-dateutil', 'decorator'],
    project_urls={
        'Bug Tracker': 'https://git.mastodont.cat/spla/Akkoma.py/issues',
    },
    keywords='akkoma api microblogging',
    classifiers=[
        "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
        "Topic :: Software Development :: Libraries :: Python Modules",
        "Topic :: Communications",
        "Intended Audience :: Developers",
        'Programming Language :: Python :: 3',
    ],
    python_requires = ">=3.8",
)  

La primera línia importa el mòdul setuptools (imprescindible per a construir el paquet). Definim la versió que li volem donar en la segona línia amb VERSION. La tercera obté el contingut de README.md que és el que es mostrarà a PyPi. setuptools.setup descriu el paquet, l'autor, la pàgina del projecte (recomanable tenir un repositori git i posar aquí les urls al mateix), els mòduls que necessitarà el nostre paquet per a executar-se (la línia install_requires), les paraules clau amb keywords (que venen a ser com els hashtags), ón es classifica el projecte amb classifiers (la llista sencera dels que podem usar és aquí) i quina versió de #Python cal per a executar el paquet amb python_requires (en aquest cas ha de ser igual o major a la versió 3.8).
Abans de construir el paquet i pujar-lo a PyPi cal que ens hi registrem. Quan ja tenim el registre fet ja ho tenim tot per a construir el paquet!

Construir el paquet

És tant fàcil com executar això en el directori arrel del projecte:

python -m build

Si no tenim instal·lat el mòdul build donarà un error. Cap problema!

pip install build  

I tornem a executar python -m build. Al final de moltes línies que ens mostrarà el constructor, veurem una línia final que diu:

Successfully built Akkoma.py-0.1.6.tar.gz and Akkoma.py-0.1.6-py3-none-any.whl

Perfecte! Tot llest per a pujar-lo a PyPi. Però un moment, primer ens cal el mòdul twine que facilita molt la tasca:

pip install twine

Ara sí:

python -m twine upload dist/*

Ens demanarà l'usuari i contrasenya de PyPi (ens hi hem registrat abans). Si tot va bé, ens donarà el missatge final on diu la URL del nostre paquet a PyPi i ja tindrem el primer paquet a l'abast de tot el món pythonista mundial.