« Distribuer un projet en python » : différence entre les versions
Contenu supprimé Contenu ajouté
Aucun résumé des modifications |
|||
Ligne 34 :
setup()
Cet exemple introduit '''setuptools''', qui est un module tiers à python que vous devez installer au préalable via <code>python -m pip install setuptools</code> et qui est un sur-ensemble de setuptools; c'est à dire qu'il permet de faire tout ce que distutils peut faire, mais en y ajoutant des fonctionnalités propres. Distutils existe depuis
# fichier setuptools/setup.py ou zc.buildout
Ligne 43 :
distutils_setup(**args)
De la même manière les fichiers qui exécutent les commandes (setup, build, sdist...) importent le fichiers de distutils et l'appellent tout en y ajoutant leurs propres fonctionnalités. ''Tout ce que l'on peut faire avec distutils, on peut le faire avec setuptools'' (ou presque<ref>https://setuptools.readthedocs.io/en/latest/deprecated/distutils-legacy.html</ref>). Si l'objectif de distutils est de produire des bundles installables à telle ou telle plateforme, celui de setuptools est assez multiple, mais principalement de produire des eggs spécifiques à python, et couplé avec l'utilitaire easy_install, de simplifier l'installation et la désinstallation (ce que distutils ne permet pas de faire) de paquetages en python, et distribuables sans
== Distutils ==
L'arborescence du projet doit contenir un fichier setup.py, qui contient le code python nécessaire à l'installation de votre module. Cette installation, doit aboutir à la copie des fichiers nécessaires dans le répertoire site-packages le plus pertinent. Ce procédé se fait automatiquement si le fichier setup.py contient un appel à la fonction <code>setup()</code> de <code>distutils.core</code>. Cette fonction
# setup.cfg
[toto]
Ligne 54 :
La commande toto s'exécutera avec arg1=2 at arg2=1, la ligne de commande prévaut sur le fichier de configuration.
Ne reconnaissant pas la commande toto un message d'erreur s'affiche avec la liste des commandes acceptées. Leur code source peut se trouver dans <code>Libs/distutils/commands</code>. Si vous lisez ces fichiers, et notamment la méthode <code>run</code>, vous remarquerez que beaucoup de commandes en appellent d'autres. Par exemple <code>install</code> appelle <code>build</code>, <code>build</code> peut appeller <code>build_ext</code>, <code>build_py</code>..., que chaque commande a des arguments différents qui peut altérer la course de l'installation, et des valeurs par défaut
Les principales commandes
La commande <code>build</code> copie les fichiers python dans un
Notre objectif premier était de produire un répertoire zip facilement installable avec pip, donc doit-on utiliser ici sdist ou bdist? Cela dépend du contenu de notre paquetage, si il ne contient que des fichiers en python, les deux commandes sont assez similaires, mais si ils contients du code en cython, ou des modules C/C++ natifs, alors dans le cas de sdist les clients de votre librairie doivent posséder un compilateur C (qui occupe un espace disque jusque 30 gigaoctets) et les librairies python de dev, par défaut non installées. Si vous optez pour bdist, les modules binaires doivent être compatible avec chaque machine, c'est à dire qu'une distribution bdist faite en 64 bits ne fonctionnera pas sur une machine 32 bits, un module fait avec une librairie python 3.7 probablement ne fonctionnera pas dans un environnement 3.6 (même si l'usage de l'ABI stable de python peut mitiger cela<ref>https://docs.python.org/fr/3/c-api/stable.html</ref>), une librairie construite sous mac, windows ou linux ne fonctionnera pas sur les autres machines. Nous verrons cette problématique bien plus tard car elle nécessite une machinerie complexe hors de notre propos, mais dont le mot-clé est ''continous integration'' (CI), et nous concentrons sur sdist dans la suite du livre, et sur la forme de bdist la plus simple : celle faite par et pour soi.
Qu'on utilise la commande <code>install</code>, <code>sdist</code> ou <code>bdist</code>, la commande <code>build</code> sera exécutée dans tous les cas, pour qu'elle sache quoi mettre dans la librairie, on utilise l'argument <code>py_modules</code> et <code>package</code> de <code>setup()</code>. Ceux-ci ont d'abord été mutuellement exclusifs, avant qu'il devienne possible de les utiliser en même temps. <code>py_modules</code> accepte une liste de chaines de caracteres, qui doivent correspondre à la manière dont les fichiers seront importés, par exemple un fichier <code>toto.py</code> sera importé ainsi
setup(py_modules=['toto'])
Si vous avez un autre fichier dans un sous-répertoire <code>a > b</code>, celui-ci doit contenir un fichier <code>__init__.py</code>, et vous le déclarez ainsi
setup(py_modules=['toto', 'a.b.toto'])
Cela inclura automatiquement le fichier __init__, pas besoin d'écrire <code>setup(py_modules=['toto', 'a.b.toto', 'a.b.__init__])</code>. Ces noms d'import doivent obligatoirement référencer des fichiers qui existent et se terminent par .py, se trouvent dans un répertoire contenant un fichier <code>__init__</code>. <code>py_modules</code> n'est pas compatible avec des fichiers non python (readme, ...) ou compressés (pyo, pyc) ou des paquetages PEP420.
L'option <code>package</code> est plus complexe à écrire, mais permet d'inclure tout type de fichier et d'utiliser une syntaxe de <code>glob</code><ref name="">https://docs.python.org/3/library/glob.html#glob.glob</ref>ing pour inclure rapidement des répertoires entiers de fichiers dans la librairie. Si on veut inclure les mêmes fichiers qu'avec <code>py_modules</code>, mais en plus un README, et des fichier en python compilés et de typage dans le répertoire a > b, on écrit
<nowiki>setup(package=['a.b'], package_data={'': ['README'], 'a.b': ['*.pyi', '*.pyc']}</nowiki>
<code>package</code> prend une liste de répertoires à chercher pour y trouver des fichiers en python, Si on veut ajouter d'autres fichiers que des scripts en python, on doit utiliser <code>package_data</code> qui prend un dictionnaire de champs nom de package -> liste de globs à appliquer. Le champ au nom vide <code><nowiki>''</nowiki></code> s'applique à tous les packages et à la racine du projet.
== Références ==
|