38 votos

Desarrollo de un plugin que depende de una biblioteca externa de Python

Estoy desarrollando un plugin de Python, el objetivo es integrar en QGIS las funcionalidades de una librería PyPI de Python llamada 'elevation'.

¿Existe una forma independiente del sistema operativo de instalar bibliotecas externas de Python y hacerlas disponibles para los plugins de Python?

Ya conozco los diferentes procedimientos específicos del sistema para instalar una dependencia externa de Python, lo que me gustaría es distribuir mi plugin en diferentes entornos sin que la gente se vuelva loca.

Lo que ya sé

Buscando en la web y en otras preguntas similares parece que no hay una solución independiente del sistema operativo.

Usuarios de Windows

Python está empaquetado y distribuido dentro del paquete de QGIS, por lo que para instalar librerías externas de Python hay que pasar por el Shell de OSGeo4W y usar pip desde allí.

enlaces relacionados:

Usuarios de OS X

En este caso QGIS utiliza el Python incorporado que está preempacado dentro de OS X y que se encuentra en:

/usr/bin/python

El problema aquí es que el pip instalado por defecto tiene algunas limitaciones y requiere demasiados privilegios.

Una solución rápida es utilizar home-brew para instalar Python de manera que su pip pueda ejecutarse contra un framework Python modificable por el usuario. Vea los detalles de este enfoque aquí .

Después de instalar todas las bibliotecas de Python a través de pip, sólo tienes que añadir sus directorios a la variable PATH.

Forma alternativa para los usuarios de OS X

Dentro del código del plugin Python se puede utilizar el pip proporcionado por el sistema para instalar los paquetes necesarios. A continuación, puede hacer que el paquete recién instalado sea accesible añadiéndolo a la ruta.

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

Solución casera pero que funciona (probada tanto en Linux como en OS X)

Me decidí por la vía alternativa ya que permite mantener la actualización y el mantenimiento de la biblioteca separados del plugin. Cada vez que un nuevo usuario instala el plugin la última versión de la librería de elevación se descarga directamente y se instala mediante pip dentro de un subdirectorio del 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)

8voto

romario bryan Puntos 6

La solución más conveniente para los usuarios del plugin es agrupar la rueda dentro de su plugin. Descargue wheel, colóquelo en su carpeta de plugins e impórtelo desde allí.

try:
    import elevation
except ImportError:
    import sys
    import os
    this_dir = os.path.dirname(os.path.realpath(__file__))
    path = os.path.join(this_dir, 'elevation-x.y.z-py2.py3-none-any.whl')
    sys.path.append(path)
    import elevation

3voto

user52245 Puntos 16

He trabajado un poco en esto en un proyecto recientemente. Desafortunadamente no hay una gran manera de lograr esto. Su solución es muy similar a lo que se me ocurrió, pero no hay garantía de que el usuario incluso tiene pip instalado.

Acabé incluyendo una copia de get_pip.py y utilizando execfile() para ejecutarlo en el caso de que no esté disponible.

Similar a su solución final:

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'])

Una alternativa, por supuesto, sería incluir la propia biblioteca en el directorio de tu plugin. Te arriesgas a proporcionar una versión antigua, pero teóricamente no importará.

2voto

Ben Puntos 160

Esto me ha funcionado (en def run(self)):

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

y la creación de un virtualenv.

Sin embargo, con Windows parece ser una historia diferente. Tuve problemas para instalar matplotlib.

2voto

Appu Puntos 3995

He sufrido este problema para ejecutar scripts de Python en QGIS que dependen de una biblioteca externa de Python. La solución más sencilla es instalar Boundless Desktop que viene con la línea de comandos e instala su propio python. Usando la línea de comandos puedes ejecutar e instalar (usando pip) cualquier paquete externo de python.

1voto

Mitchel Sellers Puntos 38352

Quizás puedas probar con virtualenv para instalar dependencias externas. De esta manera, no tienes que preocuparte (tanto) por el entorno del sistema.

https://www.fullstackpython.com/application-dependencies.html

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X