¿Cómo debo manejar la importación de bibliotecas de terceros dentro de mi script setup.py?

Estoy desarrollando una aplicación Python y en el proceso de bifurcar un lanzamiento. Tengo un servidor PyPI configurado en un servidor de la empresa y copié una distribución de origen de mi paquete en él.

Verifiqué que el paquete estaba alojado en el servidor y luego intenté instalarlo en mi máquina de desarrollo local. Acabé con esta salida:

$ pip3 install --trusted-host 172.16.1.92 -i http://172.16.1.92:5001/simple/  Collecting  Downloading http://172.16.1.92:5001/packages/-0.2.0.zip Complete output from command python setup.py egg_info: Traceback (most recent call last): File "", line 1, in  File "C:\Users\\AppData\Local\Temp\pip-build-ubb3jkpr\\setup.py", line 9, in  import appdirs ModuleNotFoundError: No module named 'appdirs' ---------------------------------------- Command "python setup.py egg_info" failed with error code 1 in C:\Users\\AppData\Local\Temp\pip-build-ubb3jkpr\\ 

La razón es que estoy tratando de importar una biblioteca de appdirs en mi setup.py , lo cual es necesario para que pueda calcular el argumento data_files a setup() :

 try: from setuptools import setup except ImportError: from distutils.core import setup import os from collections import defaultdict import appdirs from .version import __version__ as _version APP_NAME = '' APP_AUTHOR = '' SYSTEM_COMPONENT_PLUGIN_DIR = os.path.join(appdirs.user_data_dir(APP_NAME, APP_AUTHOR), 'components') # ... setup( # ... data_files=component_files, ) 

Sin embargo, no tengo appdirs instalados en mi máquina de desarrollo local y tampoco espero que los usuarios finales lo tengan.

¿Es aceptable confiar en bibliotecas de terceros como esta en setup.py y, de ser así, cuál es el enfoque recomendado para usarlas? ¿Hay alguna manera de garantizar que las appdirs instalación se instalen antes de que se importen en setup.py , o debo documentar que la appdirs es un paquete necesario para instalar mi paquete?

Estoy ignorando los problemas de licencia en esta respuesta. Definitivamente necesitas tener esto en cuenta antes de hacer un lanzamiento.

¿Es aceptable confiar en bibliotecas de terceros como esta en setup.py?

Sí, es aceptable, pero en general deberían minimizarse, especialmente si se trata de módulos que no tienen un uso obvio para el usuario final. A nadie le gusta tener paquetes que no necesitan o usan.

¿Cuál es el enfoque recomendado para usarlos?

Básicamente hay 3 opciones:

  • Arranquelas (por ejemplo, use pip para instalar paquetes mediante progtwigción). Por ejemplo, setuptools proporciona un archivo ez_setup.py que se puede usar para arrancar setuptools . Tal vez eso se puede personalizar para descargar e instalar appdirs .

  • Inclúyalos (especialmente si es un paquete pequeño) en su proyecto. Por ejemplo, las appdirs son básicamente un solo módulo de archivo. Bastante fácil de copiar y mantener en tu proyecto. ¡Tenga mucho cuidado con los problemas de licencia cuando haga eso!

  • Falla con gracia cuando no es posible importarlos y dejar que el usuario los instale. Por ejemplo:

     try: import appdirs except ImportError: raise ImportError('this package requires "appdirs" to be installed. ' 'Install it first: "pip install appdirs".') 

Puedes mencionar install_requires con la lista de dependencias. Por favor, consulte la guía de empaquetado de python aquí . También puede proporcionar un archivo Requirements.txt para que pueda ejecutarse a la vez utilizando “pip install -r”

Puede usar pip para instalar el paquete mediante progtwigción si la import falla:

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

En algunas circunstancias, es posible que necesite usar importlib o __import__ para importar el paquete después de pip.main o referesh la variable PATH . También podría valer la pena incluir una verificación si el usuario realmente desea instalar ese paquete antes de instalarlo.

Utilicé muchos de los ejemplos de “Instalación del módulo Python dentro del código” y no lo he intentado personalmente en los archivos setup.py , pero parece que podría ser una solución para su pregunta.