Skip to Content

Nous adressons toutes nos pensées à la famille de notre ami Jérôme !

http://www.forumsig.org/showthread.php/43488-Disparition-de-Phoenix

PyQGIS: comment créer un répertoire de travail « mobile » avec les fichiers Python de configuration .pth

Niveau Débutant
Logiciels utilisés QGIS
Dropbox - clé USB (ou autre système du même genre)
Python
Plateforme Windows | Mac | Linux | FreeBSD

Comment faire pour utiliser ses propres scripts dans la console Python de QGIS ou dans un script de la Boîte à outils de Traitements (Processing) sans en créer plusieurs copies si, comme moi, vous êtes susceptibles de travailler sur plusieurs ordinateurs avec des systèmes d'exploitation différents situés en de multiples endroits ?

Je désire en effet n'avoir qu'une seule version de ces scripts (pour leur maintenance). Ils peuvent être placés dans des dossiers  Dropbox, sur une clé USB ou n'importe quoi d'équivalent pourvu que leur contenu soit disponible partout.

(J'utiliserai ici le dossier créé par l'application Dropbox car elle est écrite en Python (voir Wikipedia: Dropbox), et qu'il est possible de manipuler le service à partir de la console Python de QGIS avec le module  Dropbox SDK)

Il s'agit ici, bien entendu, de régler le problème de l'importation de ces fichiers depuis la version de Python utilisée par QGIS, et ce, sans les déplacer.

Principes

Pour commencer l'explication, nous avons besoin d'un peu de « théorie Pythonesque ». Que se passe-t-il lorsque je veux importer un module dans la console Python ? (voir Sam et Max: Les imports en Python).

C'est le module site qui est responsable de la mise en place de l'environnement lors du démarrage de Python. Il va chercher les scripts/modules qu'il peut importer dans l'ordre suivant:

  1. le répertoire d'où je lance Python ou un script Python;
  2. le répertoire par défaut où se trouve l'exécutable de Python et plus particulièrement le dossier /lib/pythonx.x/sites-packages (/Library/Python/2.x/site-packages avec les versions de Python livrées sur les Macs). C'est la variable d'environnement PYTHONHOME;
  3. les dossiers qui sont présents sous forme de liste dans la variable d'environnement système PYTHONPATH (qui n'existe pas par défaut, il faut la créer).

Ensuite, le module place par défaut tous ces répertoires dans une simple liste qui peut être examinée avec la variable sys.path du module sys:

  • par défaut, sys.path[0] est le répertoire 1. Puisque la console Python de QGIS est elle même un script (/.../python/console/console.py), la commande me renverra uniquement le répertoire du script.
  • L'élément le plus important est le dossier site-packages. Lorsque vous installez un module avec easy_install, pip, ou setup.py install, c’est dans ce répertoire qu'il va être installé.

Si mon dossier n'est pas dans la liste:

import planargraph2 # script dans mon dossier
Traceback (most recent call last):
 File "<stdin>", line 1, in <module></module></stdin>
ImportError: No module named planargraph2

Je dois donc m’assurer que mon dossier « messcriptssqgis » soit toujours dans cette liste, quelle que soit la machine considérée pour pouvoir l'utiliser partout.

Comme toujours avec Python, il y a plusieurs solutions pour le faire:

La solution 1.: se déplacer dans les répertoires à l'aide du module os 

Puisque le répertoire de travail fait aussi partie de la liste, il suffit de s'y rendre depuis la console Python de QGIS :

Et je peux alors importer les scripts/modules qui sont présents. La solution est temporaire, je dois la réécrire à chaque fois que je veux importer quelque chose qui est dans mon dossier.

La solution 2.: la plus populaire, ajouter le dossier « messcriptssqgis » à la liste

Cela se fait avec sys.path.insert() ou sys.path.append(). Si je veux ajouter mon dossier « messcriptssqgis » à la liste  pendant ma session de travail:

import sys
# j'ajoute mon dossier au PYTHONPATH en dernière position de la liste
sys.path.append('chemin_vers/messcriptssqgis')
# j'ajoute mon dossier au PYTHONPATH en première position de la liste
sys.path.insert('chemin_vers/messcriptssqgis')

Encore une fois, la solution est temporaire, dès que je la quitte, l'ajout est annulé.

La solution 3: créer/modifier la variable d'environnement PYTHONPATH

Les deux précédentes solutions sont temporaires et je voudrai le faire de manière permanente sans devoir réécrire les lignes de commande à chaque fois. Il faut alors créer/modifier la variable d'environnement système PYTHONPATH. Elle permet d'ajouter des éléments à la liste depuis l'extérieur de Python.

  • sur Mac OS X ou Linux, il suffit d'ajouter une ligne à vos fichiers «.bash_profile », «.profile », «.bashrc »  ou autre script de login :

export PYTHONPATH=$PYTHONPATH:chemin_vers/messcriptsqgis

figure extraite de Script de Python para filtrar por patrón de texto los métodos de Clases en PyQGIS

La solution est permanente, mais peut poser des problèmes d'implantation, surtout si je n'ai pas les autorisations pour le faire. De plus si j'ai plusieurs versions de Python installées (2.x et 3.x par exemple), cela peut aussi en créer (une seule variable d'environnement système).

La dernière solution, la plus simple, mais généralement oubliée: les fichiers de configuration .pth

Tout ça, c'est bien complexe, me direz-vous, car je dois modifier cette variable d'environnement sur chaque ordinateur que je veux utiliser ou je dois écrire os.chdir() ou sys.path.append() à chaque fois que je lance QGIS.

Que diriez-vous d'un simple fichier texte avec une seule ligne à placer dans le répertoire site-packages de chaque version utilisée ?

Il existe en effet une solution généralement oubliée sur tous les sites qui traitent de cette problématique (et du livre The PyQGIS Programmer's Guide): les fichiers de configuration path (.pth). C'est pourtant très bien expliqué dans le fichier site.py de l'installation Python:

A path configuration file is a file whose name has the form
<package>.pth; its contents are additional directories (one per line)
to be added to sys.path.  Non-existing directories (or
non-directories) are never added to sys.path; no directory is added to
sys.path more than once.  Blank lines and lines beginning with
'#' are skipped. Lines starting with 'import' are executed.

Et un article très ancien,  Using .pth files for Python development, de Bob Ipolito explique très bien la démarche.

Elle consiste donc à placer dans le(s) dossier(s) site-packages un simple fichier texte avec .pth comme extension et le chemin complet du dossier comme contenu. Le nom n'a aucune importance.

contenu du fichier « messcrips.pth » sur mon Mac.

/Users/Shared/Dropbox/messcriptsqgis

Et ce dossier se trouve de fait automatiquement dans la liste de sys.path, sans aucune manipulation complémentaire et la solution est permanente.

Cette technique offre d'autres possibilités:

  • placer plusieurs répertoires (un par ligne)

/Users/Shared/Dropbox/messcriptsqgis
/Users/Shared/Dropbox/geolscript

  • cela permet à easy_install, par exemple, de gèrer la version des modules à importer à partir du fichier « easy-install.pth ».

Extrait de mon fichier « easy-install.pth »

  • cela permet aussi de modifier l'ordre d'importation d'un module pour être sûr qu'il se trouve en première position, car dans le cas où il y a en a plusieurs qui portent le même nom, c'est le premier sur la liste qui sera choisi. C'est ce que fait, entre autres, William Kyngesburye (KyngChaos) pour placer, sur Mac OS X, sa version du module osgeo en première position de la liste (fichier gdal-py2.x.pt) à l'aide de sys.path.insert() :

import sys; sys.path.insert(0,'/Library/Frameworks/GDAL.framework/Versions/1.10/Python/2.x/site-packages') (ou 1.11 maintenant)

  • d'autres utilisent cette technique pour préserver la compatibilité avec les anciennes versions du module comme PyNGL. Le fichier « Ngl.pth » ne contient qu'une ligne avec PyNGL. Il est alors possible d'importer le module avec le nom de son ancienne version.
import Ngl
# ou 
import PyNGL
  • et enfin, si la ligne commence par import, la commande sera exécutée:

import monscript; monscript.démarre()

Application avec un dossier Dropbox sur plusieurs ordinateurs

Je montre ici le résultat avec le dossier créé par l'application Dropbox (rappelons que c'est la même chose avec une clé USB). 

Conclusions

Pourquoi cet oubli relatif, cette technique est-elle considérée comme inadéquate, trop simple ?  Je ne pense pas car si vous consultez votre dossier site-packages vous pourrez constater qu'elle est très utilisée, notamment avec easy_install déjà signalé ou les gestionnaires des environnements virtuels comme virtualenvwrapper.

Elle a bien entendu certains inconvénients, surtout sur Windows (utilisable uniquement avec les modules en pur Python, problème éventuel du chemin du dossiers, etc.), mais elle me permet de n'avoir qu'une seule version de mes scripts, quel que soit l'ordinateur et quelle que soit la version de Python (2.6.x, 2.7.x) et de QGIS. Il me suffit de créer un simple fichier texte avec le chemin du dossier et de le placer dans le dossier ad hoc.

En résumé:

  • site.py ne prendra en considération que les fichiers .pth présents dans le dossier site-package. Ceux situés en dehors ne fonctionneront pas même s'ils sont dans la liste de sys.path;
  • il n' y a pas moyen de créer des fichiers .pth en cascade (un fichier .pth pointant vers un autre fichier .pth);
  • les lignes débutant par # seront considérées comme des commentaires;
  • toutes les autres lignes seront considérées comme des chemins absolus, hormis si elles commencent par import (exécutable). Il y a moyen de travailler avec des chemins relatifs, mais c'est inutile dans mon cas.

Pour moi, en tout cas:

  • plus besoin de me  tracasser avec les variables d'environnement (ce qui peut être difficile sur Windows) ni avec les os ou sys.path, et ce, sans me soucier des fichiers existants;
  • la solution est permanente;
  • ils ne fonctionnent que dans la version de Python où ils sont placés;
  • si je veux l'utiliser dans un autre environnement Python ou sur un autre ordinateur, il suffit de le copier/coller en modifiant le chemin du dossier si nécessaire (1 ligne), même avec les versions Standalone de QGIS pour Windows qui possèdent leurs propres implémentation de Python;
  • si je veux me débarrasser de l'accès aux modules, je supprime le fichier .pth;
  • j'utilise aussi la technique pour travailler en Python seul;
  • ils constituent donc pour moi, la meilleure solution et, en général, une excellente alternative aux autres solutions.
Site officiel : Python path configuration files (.pth)
Site officiel : Installing Python Modules and .pth files


Creative Commons License
licence Creative Commons Paternité-Pas d'Utilisation Commerciale-Pas de Modification 2.0 France

Commentaires

Poster un nouveau commentaire

Le contenu de ce champ sera maintenu privé et ne sera pas affiché publiquement.