Développement d'un plugin qui dépend d'une bibliothèque Python externe

29

Je développe un plugin Python, la cible intègre dans QGIS les fonctionnalités d'une bibliothèque PyPI Python appelée 'élévation'.

Existe-t-il un moyen indépendant du système d'exploitation d'installer des bibliothèques Python externes et de les rendre disponibles pour les plugins Python?

Je connais déjà les différentes procédures spécifiques au système pour installer une dépendance Python externe, ce que j'aimerais faire est de distribuer mon plugin dans différents environnements sans rendre les gens fous.

Ce que je sais déjà

En recherchant sur le Web et d'autres questions similaires, il semble qu'il n'y ait pas de solution indépendante du système d'exploitation.

Utilisateurs Windows

Python est empaqueté et distribué à l'intérieur du package QGIS, donc pour installer des bibliothèques Python externes, vous devez passer par le shell OSGeo4W et utiliser pip à partir de là.

Liens connexes:

Utilisateurs d'OS X

Dans ce cas, QGIS utilise le Python intégré qui est préemballé dans OS X et situé à:

/usr/bin/python

Le problème ici est que le pip installé par défaut a certaines limitations et nécessite trop de privilèges.

Une solution rapide consiste à utiliser home-brew pour installer Python afin que votre pip puisse s'exécuter sur un framework Python modifiable par l'utilisateur. Voir les détails de cette approche ici .

Après avoir installé toutes les bibliothèques Python via pip, il vous suffit d'ajouter leurs répertoires à la variable PATH.

Autre moyen pour les utilisateurs d'OS X

A l'intérieur du plugin Python, vous pouvez utiliser le pip fourni par le système pour installer les packages requis. Ensuite, vous pouvez rendre le package juste installé accessible en l'ajoutant au chemin.

import sys
import pip
pip.main(['install','--target=/Devel/test', 'elevation'])
sys.path.append("/Devel/test")

Solution maison mais fonctionnelle (testée sur Linux et OS X)

J'ai décidé d'opter pour l'alternative car elle permet de garder la mise à jour et la maintenance de la bibliothèque séparées du plugin. Chaque fois qu'un nouvel utilisateur installe le plugin, la dernière version de la bibliothèque d'élévation est directement téléchargée et installée par pip dans un sous-répertoire du plugin.

self.plugin_dir = os.path.dirname(__file__)
self.elevation_dir = os.path.join(self.plugin_dir, 'elevation')

# Checking the presence of elevation library
try:
    import elevation
except:
    pip.main(['install', '--target=%s' % self.elevation_dir, 'elevation'])
    if self.elevation_dir not in sys.path:
        sys.path.append(self.elevation_dir)
Ingénieur-G
la source
Cette procédure est uniquement pour Windows car le système d'exploitation Unix (Linux, Mac OS X) utilise la version standard de Python installée
gène
Je le sais, j'enrichissais ma question, maintenant il y a une section utilisateurs OS X qui explique comment le faire sur un mac.
Engineer-G
1
Vous pouvez parfaitement installer pip dans Apple Python. QGIS utilise cette version et pas d'autres versions (Homebrew, Anaconda et autres). Si vous souhaitez utiliser le Homebrew Python, vous devez installer la version Homebrew de QGIS
gène
3
S'il s'agit d'une bibliothèque python pure, vous pouvez simplement distribuer la bibliothèque tierce avec votre plugin en tant que sous-package / module.
user2856

Réponses:

2

J'ai souffert de ce problème pour exécuter des scripts Python dans QGIS qui dépend d'une bibliothèque Python externe. La solution la plus simple consiste à installer Boundless Desktop fourni avec la ligne de commande et installe son propre python. En utilisant la ligne de commande, vous pouvez exécuter et installer (à l'aide de pip) tout package externe de python.

osmjit
la source
1

J'ai travaillé un peu sur ce projet récemment. Malheureusement, il n'y a vraiment pas un excellent moyen d'y parvenir. Votre solution est très similaire à ce que j'ai proposé, mais il n'y a aucune garantie que l'utilisateur ait même installé pip.

J'ai fini par inclure une copie de get_pip.py et en utilisant execfile () pour l'exécuter dans le cas où il n'est pas disponible.

Semblable à votre solution finale:

self.plugin_dir = os.path.dirname(__file__)

try:
    import pip
except:
    execfile(os.path.join(self.plugin_dir, get_pip.py))
    import pip
    # just in case the included version is old
    pip.main(['install','--upgrade','pip'])

try:
    import somelibrary
except:
    pip.main(['install', 'somelibrary'])

Une alternative, bien sûr, serait d'inclure la bibliothèque elle-même dans le répertoire de votre plugin. Vous risquez de fournir une ancienne version, mais en théorie cela n'a pas d'importance.

Jesse McMillan
la source
1

Cela a fonctionné pour moi (en def run (auto)):

    def load_libraries(self):
        import_path = os.path.join(self.plugin_dir, 'lib/python2.7/site-packages')
        sys.path.insert(0, import_path)

et la mise en place d'un virtualenv.

Avec Windows, cela semble être une autre histoire. J'ai eu du mal à installer matplotlib.

geekdenz
la source