Dans cet article, nous vous guiderons pour dompter votre python à l’aide d’un environnement de travail isolé.

Le langage python fait partie des langages le plus populaires et le plus utilisé selon les années. Savoir coder en python est une chose, maitriser son environnement de travail en est une autre. Les personnes les moins aguerries avec le langage découvriront au travers de cet article une nouvelle manière de développer : en toute sécurité.

Le python

Le python est un langage haut niveau relativement facile à prendre en main. On peut facilement écrire un morceau de code en quelques lignes.

print("Hello", "World!")

Et voilà ! Bon d’accord, ça ne vole pas très haut. Allons un peu plus loin !

Le python, comme la plupart des langages, permet d’importer des librairies externes pour faciliter le développement ou renforcer les capacités de son code.

Pour réaliser un appel HTTP, la libraire native urllib3 permet d’exécuter une requête.

>>> import urllib3
>>> http = urllib3.PoolManager()
>>> r = http.request('GET', 'http://httpbin.org/robots.txt')

D’autres libraires permettent de réaliser la même fonction en plus rapide et simple, j’ai la librairie requests en tête.

>>> import requests
>>> r = requests.get('http://httpbin.org/robots.txt')
>>> r.status_code
200
>>> r.text
'User-agent: *\nDisallow: /deny\n'
>>> r.url
'http://httpbin.org/robots.txt'

En exécutant le code, vous remarquerez que le module requests n’est pas nécessairement installé.

On entre dans le vif du sujet !

Allez, c’est parti ! On installe la libraire !

pip install requests

En poussant le vice jusqu’au bout, j’ai besoin d’installer d’autres librairies python, alors je les installe…

Maintenant que j’ai terminé mon projet, je récupère le projet d’un copain pour l’aider à le maintenir, mais problème, il n’utilise pas les mêmes versions de librairies que moi =O

Eh là, c’est la panique !

Résultat

  • J’ai installé des modules python sur ma machine
  • Je dois les réinstaller à chaque projet

Cette approche comporte quelques contraintes,… beaucoup en définitif !

C’est pour cette raison que les virtual environments ont été implémenté en python. Ils permettent :

  • Isoler les environnements d’exécution
  • Exécuter des versions différentes de python
  • Installer les modules adéquats pour chaque projet (= virtual environment)
  • Rendre l’installation reproductible et stable

Son terrarium

Le tour du bocal

Vous l’aurez vite compris, le terrarium du python représente en réalité l’environnement virtuel (ou virtual environment).

Il existe plusieurs outils pour créer ces fameux “virtual environments” :

Tous sont similaires, je vous laisserai faire votre choix final. Dans la suite de cet article, je me focaliserai sur mon préféré : pipenv.

Mon préféré, c’est le pipenv

Pipenv est simple et robuste et prend le meilleur des 2 mondes : pratique et efficace. Après plusieurs années d’expérience dessus, je n’ai jamais trouvé de cas limites qui m’ont empêché de travailler correctement et me faire regretter mon choix.

Le principe du virtual env est d’utiliser le binaire python de votre machine, mais d’installer les packages (également appelés module ou librairies) dans un répertoire orienté utilisateur.

Ainsi le binaire python pointe bien vers mon système :

$ which python3
/usr/bin/python3

Les packages de la machine, installé avec pip, sont toujours au même emplacement :

>>> site.getusersitepackages()
'/home/germainlef/.local/lib/python3.8/site-packages'

Alors que les packages de mon projet sont cantonnés à un tout autre espace :

>>> site.getsitepackages()
['/home/germainlef/.local/share/virtualenvs/discover-pipenv-T_-c2_am/lib/python3.8/site-packages', '/home/germainlef/.local/share/virtualenvs/discover-pipenv-T_-c2_am/local/lib/python3.8/dist-packages', '/home/germainlef/.local/share/virtualenvs/discover-pipenv-T_-c2_am/lib/python3/dist-packages', '/home/germainlef/.local/share/virtualenvs/discover-pipenv-T_-c2_am/lib/python3.8/dist-packages']

Un répertoire sort clairement : /home/germainlef/.local/share/virtualenvs/discover-pipenv-T_-c2_am/, c’est le répertoire virtuel dédié à mon projet qui s’appelle ici discover-pipenv.

L’origine du monde reptilien

Pour initialiser un virtual env, il est conseillé de définir la version de python à utiliser, notamment quand on héberge plusieurs versions du reptile.

mkdir discover-pipenv
cd !$
pipenv --python=3.8
Creating a virtualenv for this project…
Pipfile: /home/germainlef/discover-pipenv/Pipfile
Using /usr/bin/python3.8 (3.8.11) to create virtualenv…
⠦ Creating virtual environment...created virtual environment CPython3.8.11.final.0-64 in 401ms
  creator CPython3Posix(dest=/home/germainlef/.local/share/virtualenvs/discover-pipenv-T_-c2_am, clear=False, global=False)
  seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/home/germainlef/.local/share/virtualenv)
    added seed packages: pip==21.2.4, setuptools==58.1.0, wheel==0.37.0
  activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator

✔ Successfully created virtual environment!
Virtualenv location: /home/germainlef/.local/share/virtualenvs/discover-pipenv-T_-c2_am
Creating a Pipfile for this project…

Ainsi, j’ai créé le répertoire discover-pipenv, j’entre à l’intérieur et j’initialise l’environnement virtuel.

La création du venv initialise le fichier Pipfile qui contient la définition de l’environnement.

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]

[requires]
python_version = "3.8"

Le peuplement

Maintenant que le venv est créé, il nous est possible d’ajouter et installer les packages dont nous avons besoin.

Commençons avec le paquet de l’introduction : requests, pour faire des requêtes http.

pipenv install requests
Installing requests…
Adding requests to Pipfile's [packages]…
✔ Installation Succeeded
Pipfile.lock not found, creating…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Building requirements...
Resolving dependencies...
✔ Success!
Updated Pipfile.lock (fbd99e)!
Installing dependencies from Pipfile.lock (fbd99e)…
     ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 0/0 — 00:00:00

Le fichier Pipfile s’est vu ajouter la ligne du package installé. On aperçoit enfin la force et la simplicité de l’outil.

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]
requests = "*"

[requires]
python_version = "3.8"

Pour supprimer le package, rien de plus simple que de le désinstaller :

pipenv uninstall requests

On revient donc à l’état initial. Easy peasy !

Dominer le territoire

Il serait ennuyeux de tester aveuglément notre code sans pouvoir l’ajuster au préalable.

Vous pouvez entrer dans le virtual env pour y tester des commandes :

pipenv install requests
pipenv run python

Répétons les commandes de l’introduction :

>>> import requests
>>> r = requests.get('http://httpbin.org/robots.txt')
>>> r.status_code
200
>>> r.text
'User-agent: *\nDisallow: /deny\n'
>>> r.url
'http://httpbin.org/robots.txt'

Et maintenant l’exécuter à même le fichier main.py :

import requests

r = requests.get('http://httpbin.org/robots.txt')
print(r.status_code)
print(r.text)
print(r.url)
pipenv run python main.py

On obtient le même résultat, pas très surprenant.

Un monde a plusieurs étages

Quand on développe, on utilise régulièrement des packages destinés au test, mais qui n’ont pas vocation à être déployés en production.
Pipenv implémente le flag --dev à ajouter à l’installation du package.

pipenv install --dev pytest

Le fichier Pipfile s’en trouve altéré à son tour :

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]
pytest = "*"

[packages]
requests = "*"

[requires]
python_version = "3.8"

On pourra ainsi reproduire la création complète de l’environnement en utilisant la commande suivante :

pipenv update --dev

Cette commande fonctionne également, et surtout, sans le flag --dev.

La naissance des packages

Quand on développe des packages en python, on a nécessairement besoin d’y accéder au sein même du répertoire de travail. On peut donc oublier d’installer le paquet avec pipenv install.

Pipenv fournit la possibilité d’utiliser un répertoire comme package python en l’indiquant dans le Pipfile. Ajoutons un package nommé mynewpackage dans notre Pipfile :

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]
mynewpackage = {path = "."}

[requires]
python_version = "3.8"

Mais ce n’est pas tout !

Quand on développe des packages, on a également besoin que nos modifications soient prises en compte pour tester dans l’environnement virtual. De base, tout est en lecture seule, rendant ce comportement impossible.

Pipenv permet de rendre un package local modifiable, ça se passe une nouvelle fois dans le Pipfile, avec le même exemple :

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]
mynewpackage = {editable = true, path = "."}

[requires]
python_version = "3.8"

Pour que ce soir plus parlant, vous pouvez faire un tour sur le code source d’un package que je maintiens pour mieux comprendre le mécanisme : germainlefebvre4/libtado.

Conclusion

Dans ce bref article, je vous ai montré les principaux rouages de pipenv pour créer un environnement virtuel pour vos projets python. Vous pouvez maintenant polluer votre environnement virtual sans pour autant polluer votre système.

J’espère que ces quelques lignes vous ont aidé à y voir plus clair dans l’utilisation de pipenv.

Dans un prochain article, nous verrons comment scraper un site web avec scrapy.