Un projet Python¶
Lorsqu'on se lance dans un projet il est important de définir une structure qui permettra un développement harmonieux. En Python il existe un certain nombre de bonnes pratiques (qui peuvent évoluer). Un projet comporte plusieurs parties :
- le code du projet (bien sûr)
- les tests qui garantissent le bon fonctionnement
- la documentation qui aident les autres (et soi-même)
et comme on le verra des fichiers qui indiquent les dépendences du projet et d'autres choses bien pratiques.
Dans cette feuille on se concentre sur le premier point à savoir comment ranger le code.
Toute cette partie doit être testée sur son ordinateur sans Jupyter. Cela implique d'installer Python et les différentes bibliothèques nécessaire.
Module¶
Un module est un fichier mon_module.py
avec tout ce qu'il contient
- des fonctions
- des variables
- d'autres choses éventuellement
L'intérêt d'un module c'est qu'on peut l'importer pour utiliser son contenu : import mon_module
Attention, il faut que le fichier importé soit dans le même répertoire que le fichier qui l'importe. Pour avoir plus de liberté on utilise les packets.
Packet¶
Un paquet est un ensemble de modules (fichiers Python) dans un même répertoire avec un fichier __init__.py
dedans. Ce fichier
peut être vide.
!ls -l package
total 8 -rw-rw-r-- 1 ricou ricou 937 mai 26 11:51 factorial.py -rw-rw-r-- 1 ricou ricou 0 mai 24 20:08 __init__.py drwxrwxr-x 2 ricou ricou 4096 mai 24 20:08 __pycache__
On importe un module du packet ainsi :
import package.factorial as fa
fa.factorial(3)
6
On peut aussi importer la fonction du module demandé :
from package.factorial import factorial
factorial(3)
6
Note : le répertoire code
a aussi le même fichier factorial.py
mais comme il n'a pas de fichier __init__.py
on ne peut pas utiliser import code.factorial
.
Les packets sont recherché dans la liste des répertoires stockés dans sys.path
.
import sys
sys.path
['/home/ricou/enseignement/python/python-big-data/notebooks/lesson2 Deeper in Python', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '', '/home/ricou/.local/lib/python3.8/site-packages', '/usr/local/lib/python3.8/dist-packages', '/usr/lib/python3/dist-packages', '/usr/local/lib/python3.8/dist-packages/IPython/extensions', '/home/ricou/.ipython']
Comme le répertoire package
est dans le répertoire du cours lequel est le premier de la liste, import package.factorial
prend le fichier factorial.py
de ce répertoire. On note que si je désire que ce paquet soit accessible depuis n'importe où sur ma machine, je peux le recopier dans $HOME/.local/lib/python3.8/site-packages
(à adapter en fonction de la version de Python qu'on a).
Lorsqu'on teste le code qu'on distribue, il est préférable que le paquet utilisé soit celui installé dans .../site-packages
et non celui du sous répertoire du répertoire courant. Cela garantit que le système de création du paquet n'oublie rien.
Enfin il est possible de modifier cette liste, par exemple : sys.path.insert(0,"/tmp/")
.
Organiser son projet¶
Les bonnes pratiques indiquées au début veulent que
- le code du projet soit dans le répertoire
src
- les tests soient dans
tests
- la documentation soit dans
doc
Le projet peut avoir plusieurs paquet ou sous-paquets qui respectent l'arborescence suivante :
project/
└── src/
└── example_pkg/
└── __init__.py
Structure pour un paquet¶
Pour créer son paquet on ajoute les fichiers suivants :
packaging_tutorial/
├── LICENSE
├── pyproject.toml
├── README.md
├── src/
│ └── example_pkg/
│ └── __init__.py
└── tests/
Poetry¶
On va utiliser le gestionnaire de paquet Poetry pour
- créer la structure de notre projet
- créer le paquet de notre projet (en remplacement de setuptools)
- créer des environnements virtuels (en remplacement de pyenv)
- installer les paquets nécessaires (en remplacement de pip)
Créer le projet¶
Pour créer le répertoire du projet ainsi que sa structure et certains fichiers taper ces commandes dans un terminal :
poetry new --src mon_projet
cd mon_projet
mv README.rst README.md
ls -R
On a le fichier pyproject.toml
qui contient les dépendences minimalistes du projet. On peut le modifier
en ajoutant un description et le nom du fichier readme par exemple :
name = "projet_alpha"
version = "0.1.0"
description = "Blabla alpha est top"
authors = ["Olivier Ricou <ricou@lrde.epita.fr>"]
readme = 'README.md'
[tool.poetry.dependencies]
python = "^3.8"
[tool.poetry.dev-dependencies]
pytest = "^5.2"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
On peut chercher et ajouter des dépendences avec poetry search
et poetry add
.
On peut aussi éditer le fichier et indiquer clairement les
versions que l'on désire en suivant les règles de version de la doc.
Après toute modification de ce fichier il faut mettre à jour Poetry : poetry update
.
Il est ensuite possible de regarder toutes les dépendences du projets :
poetry show --tree
numpy 1.18.5 NumPy is the fundamental package for array computing with Python.
poetry 1.1.6 Python dependency management and packaging made easy.
├── cachecontrol >=0.12.4,<0.13.0
│ └── lockfile >=0.9
│ └── sgpack >=0.5.2
...
Gestion des envionnements¶
Poetry permet d'avoir plusieurs environnement, c'est très utile pour tester si notre projet fonctionne pour différentes version de Python et des bibliothèques utilisée. Les commandes de base sont :
poetry env use 3.5 |
lance un environnement virtuel avec Python 3.5. Faire ensuite poetry update pour avoir les bibliothèques indiquées dans pyproject.toml |
poetry env list |
donne la liste des environnements virtuels installés |
poetry run python |
lance Python dans l'environnement où on se trouve |
poetry shell |
lance un terminal dans l'environnement où on se trouve |
Note : pour créer un environnement virtuel avec une version de Python, il faut que cette version soit installée sur l'ordinateur.
Création d'un paquet¶
La création d'un paquet est simplissime : poetry build
et on a le résultat dans le répertoire dist
.
Pour installer le paquet sur PyPI ou dans un dépôt privé, il suffit de faire poetry publish
(cf https://python-poetry.org/docs/repositories/ pour les détails).
Pour ajouter les tests à la tarball, il faut mettre dans la partie [tool.poetry]
de pyproject.toml
:
packages = [ { include = "src", format = "sdist" },
{ include = "tests", format = "sdist" },
]
{{ PreviousNext("12 xml.ipynb", "91 Tests.ipynb") }}