Empaquetage des projets Python pour Debian / Raspbian avec dh-virtualenv
Cet article a pour but d'expliquer certaines choses aux développeurs qui n'utilisent pas beaucoup Python et qui pourraient avoir des difficultés avec certains concepts.
Je recommande vivement la lecture de l'article suivant comme introduction aux concepts abordés ici :
pypi.org
pypi.org est un dépôt officiel de logiciels pour le langage de programmation Python. Il comprend des bibliothèques que nous voulons utiliser dans nos projets, mais qui ne sont pas livrées par défaut avec Python.
Le problème
Notre objectif est d'empaqueter une application écrite en Python (ciblant Python3) sous forme de paquet .deb pour Raspbian (qui est, tout bien considéré, vraiment équivalent à Debian).
Notre application a des dépendances sur plusieurs bibliothèques Python.
Par exemple, nous aimerions utiliser le demande bibliothèque. La bibliothèque requests elle-même dépend d'autres bibliothèques, par exemple chardet, urllib3, etc.
La gestion manuelle de ces dépendances et l'envoi manuel du code de bibliothèque requis sont intrinsèquement peu pratiques.
pip
Python possède son propre système de gestion des paquets et des dépendances, appelé pip
pip vous permet d'installer des bibliothèques et des applications python, afin que votre propre code puisse utiliser ces bibliothèques.
Ici, il y a deux problèmes :
- nous voulons expédier le paquet comme un Paquet Debianpour que les utilisateurs finaux puissent les installer facilement. Nous pouvons supposer que sur un nombre significatif de systèmes cibles, les bibliothèques python appropriées n'auront pas été installées par l'utilisateur.
- si nous essayons d'installer ces bibliothèques à l'échelle du système au nom de l'utilisateurnous risquons de rompre la compatibilité avec d'autres paquets (par exemple, en raison de changements d'API entre les versions des bibliothèques).
Nous avons donc besoin d'une solution.
virtualenv
virtualenv nous permettra de créer des environnements virtuels pour Python.
Dans ces environnements virtuels, nous avons :
- notre propre interpréteur Python
- des copies des bibliothèques standard requises
- notre propre tuyau
- notre propre bibliothèque "à l'échelle du système
Partie pratique : Essai de virtualenv
Installez virtualenv (dans le cadre de dh-virtualenv, que nous aborderons dans un moment) en faisant :
sudo apt install dh-virtualenv
Comme les requêtes sont déjà installées dans tout le système sur ma boîte de test, nous allons utiliser un paquet différent comme exemple. randstr vous permettra de générer une chaîne aléatoire.
Vérifiez si randstr est installé dans tout le système :
pip3 show randstr
Cela ne devrait rien donner. Indiquant que ce paquet n'est pas installé dans tout le système :
Nous allons maintenant créer un environnement virtuel. Le dossier de l'environnement virtuel ne doit PAS nécessairement se trouver à l'intérieur de votre dossier de code, mais il le peut. Vous devriez l'ignorer dans GIT.
disons que nous avons un répertoire /home/pi/tutorial
Passez dans ce répertoire, et créez un nouveau dossier d'environnement env :
cd /home/pi/tutorial
quel python3
virtualenv -p /usr/bin/python3 env
Note : vous devez spécifier l'interpréteur Python si vous voulez Python 3, car sinon Python 2 sera utilisé. J'utilise Python 3. (Exécution de virtualenv avec l'interpréteur /usr/bin/python2)
which python3 vous dira où réside le binaire python3, ajustez le chemin pour virtualenv en conséquence.
activer l'environnement :
source env/bin/activate
(Ce chemin de commande suppose que vous êtes resté dans le répertoire du tutoriel). Veuillez également noter qu'il ne s'agit pas d'un script exécutable - vous devez utiliser la commande source pour l'utiliser avec votre terminal bash.
Remarquez, comment (env) est ajouté avant votre invite de commande :
Cela signifie que l'environnement est actif. Maintenant vous pouvez relancer pip3, mais cette fois-ci pip3 va effectuer son travail sur l'environnement virtuel :
pip3 show randstr
demandes de spectacles pip3
ne devrait toujours rien donner. La deuxième ligne ne donnera également rien - ce qui montre que (si les demandes sont installées dans tout le système) nous sommes bien dans un environnement virtuel.
Maintenant, installez randstr :
pip3 install randstr
et vérifiez à nouveau, s'il est installé :
pip3 show randstr
Cette fois, il montre que randstr est installé. Il a été installé dans env/lib/python3.5/site-packages :
Pendant que l'environnement est encore activé, écrivons un petit exemple d'application Python :
nano sample.py
collez le code suivant, générant une chaîne aléatoire en utilisant la nouvelle bibliothèque que nous venons d'installer :
from randstr import randstr
print("hello world")
print(randstr())
et sauvegarder.
Exécutez le code en utilisant python3 :
python3 sample.py
tant que l'environnement est encore actif, cela fonctionnera :
Il est maintenant temps de quitter l'environnement, pour voir si le code s'exécute toujours :
désactiver
Votre promptitude va revenir à la normale. Et
python3 sample.py
affichera un message d'erreur, indiquant qu'aucun module 'randstr' n'existe sur votre système. C'est exactement le comportement que nous voulons !
Vous pouvez jeter un coup d'oeil au dossier env, pour voir comment il fournit toutes les choses nécessaires pour exécuter votre code Python, y compris les bibliothèques, l'exécutable python, pip, et plus encore.
Empaquetage de virtualenv Debian avec dh-virtualenv
OK, maintenant que les bases sont posées, ce que nous voulons, c'est empaqueter un virtualenv avec notre code, afin que notre application fonctionne de manière fiable et sans perturber les autres applications sur les ordinateurs de nos utilisateurs.
C'est là que dh-virtualenv dh-virtualenv est un ajout aux scripts de construction de Debian, qui vous permet d'empaqueter des environnements virtuels.
Nous devons créer une structure de base pour notre nouveau paquet. C'est là que emporte-pièce vous aidera.
emporte-pièce
cookiecutter crée pour vous de nouveaux projets à partir de modèles, ce qui réduit les frais généraux et le temps que vous consacrez au développement et à la compréhension des nombreux fichiers nécessaires.
https://cookiecutter.readthedocs.io/en/latest/
sudo apt install cookiecutter
Note : le paquet python3-cookiecutter fournira un module Python pour Python 3. Ce que nous voulons, c'est l'application elle-même, qui est installée avec le paquet cookiecutter, comme indiqué ci-dessus. Cela pourrait tirer dans Python 2, mais - oh bien.
cookiecutter n'est pas nécessaire pour vos utilisateurs finaux, il est seulement utilisé pour créer plusieurs fichiers pour votre paquet.
créer un répertoire de projet exemple, dans lequel nous allons appliquer le modèle (je suis toujours dans le répertoire tutorial) :
mkdir sampleproject
cd sampleproject
En utilisant un moule spécial pour dh-virtualenv nous pouvons configurer plusieurs des fichiers nécessaires :
https://github.com/Springerle/dh-virtualenv-mold
emporte-pièce https://github.com/Springerle/dh-virtualenv-mold.git
Cela vous posera plusieurs questions.
Notez que le dossier doit être nommé debian, même si vous empaquetez pour Raspbian - gardez donc le nom debian.
Cela va installer les fichiers suivants :
Maintenant vous devez exécuter les commandes suivantes, selon les instructions sous le dh-virtualenv-mold :
sudo apt-get install build-essential debhelper devscripts equivssudo mk-build-deps --install debian/control
Pour construire le paquet plus tard, vous devez exécuter la commande suivante à partir du répertoire de premier niveau de votre projet :
dpkg-buildpackage -uc -us -b
Pour l'instant, cependant, la commande échouera parce que setup.py est manquant. Nous arriverons à setup.py et requirements.txt dans un court instant :
/usr/bin/python3 : Impossible d'ouvrir le fichier 'setup.py' : [Errno 2] Pas de tel fichier ou répertoire
Informations sur les dossiers individuels
journal des modifications
Ce fichier contiendra les informations sur la version du paquet. Vous pouvez le mettre à jour à l'aide d'un outil spécial, dch.
Ce fichier n'est pas un journal des modifications de votre application, mais simplement un journal des modifications de l'emballage de votre application.
compat
Ce fichier comprend un chiffre magique spécial "9". (pour des questions de compatibilité, il est bon de le laisser tel quel)
contrôle
C'est le fichier principal pour définir les paramètres des paquets et les dépendances au niveau de Debian. Si votre application dépend, par exemple, de l'installation d'omxplayer, il faudra l'indiquer ici en tant que dépendance :
Source : projet pilote
Section : contrib/python
Priorité : supplémentaire
Mainteneur : Maximilian Batz
Compatibilité : debhelper (>= 9), python, python-dev, dh-virtualenv (>= 0.10), tar
Standards-Version : 3.9.5
Page d'accueil : https://picockpit.com
Paquet : sampleproject
Architecture : toute
Prédépendants : dpkg (>= 1.16.1), python2.7 | python3, ${misc:Pre-Depends}
Dépend : ${python:Depends}, ${misc:Depends}.
Description : Un paquet d'exemple pour démontrer l'empaquetage de virtualenv Debian avec dh-virtualenv
.
Il s'agit d'une distribution de "sampleproject" en tant que projet autonome.
Python virtualenv emballé dans un paquet Debian (paquet " omnibus "),
tous les passagers à bord). Le virtualenv empaqueté est maintenu en synchronisation avec
l'interprète de l'hôte automatiquement.
.
Voir https://github.com/spotify/dh-virtualenv pour plus de détails.
Vous voudrez également modifier la description longue.
cookiecutter.json
Comprend vos paramètres initiaux. Non requis pour l'emballage.
copyright
Votre fichier de copyright, avec votre licence (par exemple MIT). Il est pré-rempli avec votre nom, l'année, l'adresse électronique et "certains droits réservés".
règles
C'est un Makefile, pour construire réellement votre paquet. Il est pré-rempli par le modèle cookiecutter.
exemple de projet.liens
Ce fichier vous permet de créer des liens lors de l'installation . Le nom du fichier comprendra le nom de votre projet au lieu de exemple de projet.
Réf : https://stackoverflow.com/questions/9965717/debian-rules-file-make-a-symlink
projet type.postinst
Ce fichier vous permet d'exécuter des étapes de configuration supplémentaires après l'installation (par exemple, l'activation de votre script python en tant que service). Le nom du fichier comprendra le nom de votre projet au lieu de exemple de projet.
exemple de projet.triggers
D'après ce que j'ai compris, c'est pour que dh-virtualenv installe un interpréteur python plus récent dans l'environnement virtuel à expédier, si celui du système (votre boîte de développement) est mis à jour. Le nom du fichier comprendra le nom de votre projet au lieu de exemple de projet.
Cela peut être ou non le cas, je ne l'ai pas testé.
setup.py
Comme mentionné ci-dessus, nous avons besoin d'un setup.py fichier. C'est la manière standard dont les applications sont empaquetées sous Python (elles sont livrées avec un setup.py, qui est exécuté pour diverses tâches liées à l'empaquetage).
Un setup.py simple peut être vu sur cette page :
https://github.com/benjaminirving/python-debian-packaging-example/blob/master/setup.py
Toutes les entrées de ces fichiers ne sont pas nécessaires. Par exemple, vous pouvez laisser de côté les classificateurs. J'ai le setup.py suivant :
Remarque : le numéro de version et les autres informations contenues ici concernent votre paquet Python (qui sera créé au cours de la construction d'un paquet Debian avec votre virtualenv).
Structure pour votre code
Votre code se trouve maintenant dans un sous-répertoire du répertoire principal de sampleproject :
Dans ce cas, le sous-répertoire porte le même nom que le répertoire principal.
Notez que le fichier __init__.py
Le fichier sample.py est celui que nous avons utilisé plus haut, mais un peu retravaillé pour ressembler à ceci :
En outre, j'ai mis en place un environnement virtuel pour les tests tout en développant à l'intérieur du répertoire principal (de premier niveau) du projet pilote :
virtualenv -p /usr/bin/python3 sp_env
appelé sp_env pour l'environnement de l'échantillon de projet
Entrer dans l'environnement :
source sp_env/bin/activate
Installez la bibliothèque randstr dans cet environnement :
pip3 install randstr
et maintenant nous pouvons exécuter le code :
python3 sampleproject/sample.py
OK. Quitter l'environnement ( ! important !)et essayez à nouveau de construire le paquet :
désactiver
dpkg-buildpackage -us -uc
Par défaut (à cause de l'emporte-pièce), votre paquet sera créé pour être installé dans /opt/venvs/ :
Nouvel exécutable python dans /home/pi/tutorial/sampleproject/debian/sampleproject/opt/venvs/sampleproject/bin/python3
Cela peut être modifié dans le debian/rules fichier.
Maintenant, le paquet a été construit, et déposé en dehors du répertoire supérieur de sampleproject (à l'intérieur du répertoire tutorial) :
Vous pouvez installer le fichier .deb en utilisant dpkg :
sudo dpkg -i sampleproject_0.2.1+nmu1_armhf.deb
Voir les résultats de l'installation avec
arbre /opt/venvs
127 répertoires et 945 fichiers ont été installés.
Maintenant vous pouvez essayer d'exécuter le projet d'exemple en utilisant
/opt/venvs/sampleproject/bin/sampleproject
exigences / dépendances
L'application ne s'exécute pas comme (peut-être) prévu, mais lance une erreur sur la non présence de randstr. Que se passe-t-il ?
La raison en est que dh-virtualenv ne connaît pas l'exigence que nous avons, de regrouper le paquet randstr pendant le processus de construction. C'est la dernière pièce du puzzle.
Les exigences doivent être ajoutées à la setup.pycomme un moyen d'indiquer à pip les paquets supplémentaires qui doivent être installés dans l'environnement virtuel en cours de création.
ajoutez ce qui suit à setup.py :
install_requires=[
randstr
]
Le fichier entier ressemblera alors à ceci :
Dans mes tests, le fichier requirements.txt placé en haut de l'écran a donné les résultats suivants pas influencer le comportement de dh-virtualenv et des paquets Python réellement inclus dans le paquet Debian. Si vous le souhaitez toujours, voici comment :
pip vous offre un moyen de sortir les dépendances exactes que vous avez utilisées pour le développement dans l'environnement virtuel. Entrez dans l'environnement virtuel :
source sp_env/bin/activate
Et créez le fichier requirements.txt :
pip3 freeze > requirements.txt
Maintenant vous pouvez jeter un coup d'oeil à ce fichier :
cat requirements.txt
Même si ce fichier ne semble pas être utilisé par dh-virtualenv (peut-être doit-il être placé dans un autre sous-répertoire), c'est une bonne référence pour vous-même, pour voir quels paquets vous devez mettre comme dépendances dans la partie install_requires de setup.py.
Notez que le fichier sampleproject.links nous a offert un moyen pratique de lier ceci dans le dossier /usr/bin, je vais donc enlever le signe de commentaire pour la prochaine construction :
Ceci étant fait, il est temps de purger le sampleproject, de le recompiler, puis de l'installer. N'oubliez pas de désactiver d'abord !
désactiver
sudo apt purge sampleproject
dpkg-buildpackage -us -uc
cd...
sudo dpkg -i sampleproject_0.2.1+nmu1_armhf.deb
Cette fois, le paquet devrait être accessible en utilisant sampleproject :
quel projet type
exemple de projet
Réf : https://packaging.python.org/discussions/install-requires-vs-requirements/
Conseil bonus : changer le lieu d'installation
/opt/venvs n'est pas un " endroit " très Debian pour mettre un paquet.
Les spécifications sont ici :
http://refspecs.linuxfoundation.org/FHS_3.0/fhs/index.html
https://unix.stackexchange.com/questions/10127/why-did-my-package-get-installed-to-opt
- /usr/local est pas pour les paquets
- /opt n'est pas destiné aux paquets Debian proprement dits (c'est pour les logiciels tiers installés par l'utilisateur).
http://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch04s06.html
Les applications peuvent utiliser un seul sous-répertoire sous le nom de /usr/lib
. Si une application utilise un sous-répertoire, toutes les données dépendantes de l'architecture utilisées exclusivement par l'application doivent être placées dans ce sous-répertoire.
https://wiki.debian.org/HowToPackageForDebian
https://www.debian.org/doc/debian-policy/ch-opersys.html#file-system-hierarchy
"L'exigence du FHS selon laquelle les fichiers statiques spécifiques à l'application et indépendants de l'architecture doivent se trouver dans /usr/share
est relaxé en une suggestion. En particulier, un sous-répertoire de /usr/lib
peut être utilisé par un paquet (ou une collection de paquets) pour contenir un mélange de fichiers indépendants de l'architecture et de fichiers dépendants de l'architecture. Cependant, lorsqu'un répertoire est entièrement composé de fichiers indépendants de l'architecture, il doit être situé dans le répertoire /usr/share
."
Le meilleur emplacement me semble être /usr/share
Nous devons modifier deux fichiers :
dans debian/rules DH_VIRTUALENV_INSTALL_ROOT doit être changé en /usr/share, comme ceci :
et debian/sampleproject.links doivent être modifiés :
Aussi, nous ferons une nouvelle entrée dans le changelog :
dch -i
modifier simplement le texte, pour refléter un nouveau numéro de version, et une entrée pour le changelog.
Ensuite, le projet peut être reconstruit :
dpkg-buildpackage -us -uc
Après l'installation, vous pouvez vérifier qu'effectivement le nouvel emplacement est utilisé :
Le paquet occupera environ 16 Mo sur votre système cible, grâce à l'environnement virtuel et à tout ce qui est livré avec. Cela pourrait probablement être réduit par certains paramètres, mais cet exercice est laissé au lecteur.
Amusez-vous bien à emballer !