requisitos.txt vs setup.py

Resuelto lucy asked hace 7 años • 5 respuestas

Empecé a trabajar con Python. He añadido requirements.txty setup.pya mi proyecto. Pero todavía estoy confundido acerca del propósito de ambos archivos. He leído que setup.pyestá diseñado para cosas redistribuibles y que requirements.txtestá diseñado para cosas no redistribuibles. Pero no estoy seguro de que esto sea exacto.

¿Cómo se pretende que se utilicen realmente esos dos archivos?

lucy avatar Apr 27 '17 20:04 lucy
Aceptado

requirements.txt:

Esto le ayuda a configurar su entorno de desarrollo.

Programas como pipse pueden utilizar para instalar todos los paquetes enumerados en el archivo de una sola vez. Después de eso, puedes comenzar a desarrollar tu script en Python. Especialmente útil si planea que otros contribuyan al desarrollo o utilicen entornos virtuales. Así es como lo usas:

pip install -r requirements.txt

Puede producirse fácilmente por pipsí mismo:

pip freeze > requirements.txt

pipautomáticamente intenta agregar solo paquetes que no están instalados de manera predeterminada, por lo que el archivo producido es bastante mínimo.


setup.py:

Esto le ayuda a crear paquetes que puede redistribuir.

El setup.pyscript está destinado a instalar su paquete en el sistema del usuario final, no a preparar el entorno de desarrollo como pip install -r requirements.txtlo hace. Consulte esta respuesta para obtener más detalles sobre setup.py.


Las dependencias de su proyecto se enumeran en ambos archivos.

AndreasT avatar Apr 27 '2017 13:04 AndreasT

La respuesta corta es que requirements.txtes solo para enumerar los requisitos del paquete. setup.pypor otro lado se parece más a un script de instalación. Si no planea instalar el código Python, normalmente solo necesitará requirements.txt.

El archivo setup.pydescribe, además de las dependencias del paquete, el conjunto de archivos y módulos que deben empaquetarse (o compilarse, en el caso de módulos nativos (es decir, escritos en C)) y metadatos para agregar a los listados de paquetes de Python ( por ejemplo, nombre del paquete, versión del paquete, descripción del paquete, autor, ...).

Debido a que ambos archivos enumeran dependencias, esto puede generar un poco de duplicación. Lea a continuación para obtener más detalles.

requisitos.txt


Este archivo enumera los requisitos del paquete Python. Es un archivo de texto plano (opcionalmente con comentarios) que enumera las dependencias del paquete de su proyecto Python (una por línea). No describe la forma en que se instala su paquete de Python. Generalmente consumirías el archivo de requisitos con pip install -r requirements.txt.

El nombre del archivo de texto es arbitrario, pero suele ser requirements.txtpor convención. Al explorar repositorios de código fuente de otros paquetes de Python, es posible que se tope con otros nombres, como dev-dependencies.txto dependencies-dev.txt. Estos tienen el mismo propósito, dependencies.txtpero generalmente enumeran dependencias adicionales de interés para los desarrolladores del paquete en particular, es decir, para probar el código fuente (por ejemplo, pytest, pylint, etc.) antes del lanzamiento. Los usuarios del paquete generalmente no necesitarán todo el conjunto de dependencias del desarrollador para ejecutar el paquete.

Si hay varias requirements-X.txtvariantes presentes, normalmente una enumerará las dependencias del tiempo de ejecución y la otra las dependencias del tiempo de compilación o de prueba. Algunos proyectos también ponen en cascada su archivo de requisitos, es decir, cuando un archivo de requisitos incluye otro archivo ( ejemplo ). Hacerlo puede reducir la repetición.

configuración.py


Este es un script de Python que utiliza el setuptoolsmódulo para definir un paquete de Python (nombre, archivos incluidos, metadatos del paquete e instalación). Al igual que requirements.txt, también enumerará las dependencias de tiempo de ejecución del paquete. Setuptools es la forma de facto de construir e instalar paquetes de Python, pero tiene sus deficiencias, que con el tiempo han generado el desarrollo de nuevos "administradores de metapaquetes", como pip. Algunos ejemplos de deficiencias de las herramientas de configuración son su incapacidad para instalar varias versiones del mismo paquete y la falta de un comando de desinstalación.

Cuando un usuario de Python lo hace pip install ./pkgdir_my_module(o pip install my-module), pip se ejecutará setup.pyen el directorio (o módulo) dado. De manera similar, cualquier módulo que tenga setup.pyse puede pipinstalar, por ejemplo, ejecutándolo pip install .desde la misma carpeta.

¿Realmente necesito ambos?


La respuesta corta es no, pero es bueno tener ambos. Logran propósitos diferentes, pero ambos pueden usarse para enumerar sus dependencias.

Hay un truco que puedes considerar para evitar duplicar tu lista de dependencias entre requirements.txty setup.py. Si ya ha escrito un setup.pypaquete completamente funcional y sus dependencias son en su mayoría externas, podría considerar tener un paquete simple requirements.txtcon solo lo siguiente:

 # requirements.txt
 #
 # installs dependencies from ./setup.py, and the package itself,
 # in editable mode
 -e .

 # (the -e above is optional). you could also just install the package
 # normally with just the line below (after uncommenting)
 # .

Es -euna opción especial pip installque instala el paquete dado en modo editable . Cuando pip -r requirements.txtse ejecuta en este archivo, pip instalará sus dependencias a través de la lista en ./setup.py. La opción editable colocará un enlace simbólico en su directorio de instalación (en lugar de un huevo o una copia archivada). Permite a los desarrolladores editar código in situ desde el repositorio sin necesidad de reinstalar.

También puedes aprovechar lo que se llama "extras de setuptools" cuando tienes ambos archivos en tu repositorio de paquetes. Puede definir paquetes opcionales en setup.py en una categoría personalizada e instalar esos paquetes solo desde esa categoría con pip:

# setup.py
from setuptools import setup
setup(
   name="FOO"
   ...
   extras_require = {
       'dev': ['pylint'],
       'build': ['requests']
   }
   ...
)

y luego, en el archivo de requisitos:

# install packages in the [build] category, from setup.py
# (path/to/mypkg is the directory where setup.py is)
-e path/to/mypkg[build]

Esto mantendría todas sus listas de dependencias dentro de setup.py.

Nota : Normalmente ejecutarías pip y setup.py desde un entorno sandbox, como los creados con el programa virtualenv. Esto evitará instalar paquetes de Python fuera del contexto del entorno de desarrollo de su proyecto.

init_js avatar Apr 06 '2018 03:04 init_js

En aras de la exhaustividad, así es como yo lo veo en 3 4 ángulos diferentes.

  1. Sus propósitos de diseño son diferentes.

Esta es la descripción precisa citada de la documentación oficial (el énfasis es mío):

Mientras que install_requires (en setup.py) define las dependencias para un único proyecto , los archivos de requisitos se utilizan a menudo para definir los requisitos de un entorno Python completo .

Mientras que los requisitos de install_requires son mínimos, los archivos de requisitos a menudo contienen una lista exhaustiva de versiones fijadas con el fin de lograr instalaciones repetibles de un entorno completo.

Pero puede que todavía no sea fácil de entender, por lo que en la siguiente sección se incluyen dos ejemplos concretos para demostrar cómo se supone que se deben utilizar los dos enfoques de manera diferente.

  1. Por lo tanto, sus usos reales son (se supone que son) diferentes.
  • Si su proyecto foose va a publicar como una biblioteca independiente (es decir, otros probablemente lo harían import foo), entonces usted (y sus usuarios intermedios) querrían tener una declaración de dependencia flexible, de modo que su biblioteca no (y no debe hacerlo). ) sea "exigente" acerca de cuál debería ser la versión exacta de SUS dependencias. Entonces, normalmente, tu setup.py contendría líneas como esta:

         install_requires=[
             'A>=1,<2',
             'B>=2'
         ]
    
  • Si simplemente desea "documentar" o "fijar" de alguna manera su entorno actual EXACTO para su aplicación bar, es decir, usted o sus usuarios desean usar su aplicación bartal como está, es decir, ejecutándola python bar.py, es posible que desee congelar su entorno para que siempre se comportaría igual. En tal caso, su archivo de requisitos se vería así:

         A==1.2.3
         B==2.3.4
         # It could even contain some dependencies NOT strickly required by your library
         pylint==3.4.5
    
  1. En realidad ¿cuál uso?

    • Si está desarrollando una aplicación barque será utilizada por python bar.py, incluso si es "sólo un script por diversión", se le recomienda utilizar requisitos.txt porque, quién sabe, la próxima semana (que resulta ser Navidad) recibirá un Le regalaron una computadora nueva, por lo que necesitaría configurar su entorno exacto allí nuevamente.

    • Si está desarrollando una biblioteca fooque será utilizada por import foo, debe preparar un setup.py. Período. Pero aun así puedes optar por proporcionar también un archivo require.txt al mismo tiempo, que puede:

      (a) estar en el A==1.2.3estilo (como se explica en el punto 2 anterior);

      (b) o simplemente contener un single mágico.

         .
      

      Este último consiste esencialmente en utilizar el requirements.txthábito convencional de documentar el paso de instalación pip install ., lo que significa "instalar los requisitos basados ​​en setup.py" sin duplicación. Personalmente, considero que este último enfoque desdibuja la línea y aumenta la confusión, pero no obstante es una forma conveniente de optar explícitamente por no fijar dependencias cuando se ejecuta en un entorno de CI. El truco se derivó de un enfoque mencionado por Donald, el mantenedor del empaquetado de Python, en su publicación de blog .

  2. Diferentes límites inferiores.

    Suponiendo que exista una enginebiblioteca con este historial:

    engine 1.1.0 Use steam
    ...
    engine 1.2.0 Internal combustion is invented
    engine 1.2.1 Fix engine leaking oil
    engine 1.2.2 Fix engine overheat
    engine 1.2.3 Fix occasional engine stalling
    
    engine 2.0.0 Introducing nuclear reactor
    

    Siga los 3 criterios anteriores y decidió correctamente que su nueva biblioteca hybrid-engineusaría a setup.pypara declarar su dependencia engine>=1.2.0,<2, y luego su aplicación separada reliable-carusaría requirements.txtpara declarar su dependencia engine>=1.2.3,<2(o tal vez desee simplemente anclar engine==1.2.3). Como puede ver, su elección de número de límite inferior sigue siendo sutilmente diferente y ninguno de ellos utiliza la última versión engine==2.0.0. Y he aquí por qué.

    • hybrid-engineDepende de engine>=1.2.0porque, la add_fuel()API necesaria se introdujo por primera vez en engine 1.2.0, y esa capacidad es necesaria hybrid-engine, independientemente de si puede haber algunos errores (menores) dentro de dicha versión y se han solucionado en las versiones posteriores 1.2.1, 1.2.2 y 1.2. 3.

    • reliable-carDepende engine>=1.2.3porque esa es la versión más antigua SIN problemas conocidos, hasta ahora. Seguro que hay nuevas capacidades en versiones posteriores, es decir, el "reactor nuclear" introducido en engine 2.0.0, pero no son necesariamente deseables para el proyecto reliable-car. time-machine( Es probable que su otro proyecto nuevo utilice engine>=2.0.0, pero ese es un tema diferente).

RayLuo avatar Dec 11 '2018 07:12 RayLuo

TL;DR

  • requirements.txtenumera dependencias concretas
  • setup.pyenumera dependencias abstractas

Un malentendido común con respecto a la gestión de dependencias en Python es si es necesario utilizar un archivo requirements.txt o setup.py para manejar las dependencias.

Lo más probable es que tengas que usar ambos para asegurarte de que las dependencias se manejen adecuadamente en tu proyecto Python.

Se supone que el requirements.txtarchivo enumera las dependencias concretas . En otras palabras, debería enumerar las dependencias fijadas (usando el ==especificador). Este archivo luego se utilizará para crear un entorno virtual de trabajo que tendrá todas las dependencias instaladas, con las versiones especificadas.

Por otro lado, el setup.pyarchivo debería enumerar las dependencias abstractas . Esto significa que debe enumerar las dependencias mínimas para ejecutar el proyecto. Sin embargo, además de la gestión de dependencias, este archivo también sirve para la distribución del paquete (por ejemplo, en PyPI).

Para una lectura más completa, puede leer el artículo requisitos.txt vs setup.py en Python en TDS.


Ahora, en adelante y a partir de PEP-517 y PEP-518, es posible que deba usar un archivo pyproject.tomlpara especificar qué desea usar setuptoolscomo herramienta de compilación y un setup.cfgarchivo adicional para especificar los detalles. Para más detalles puedes leer el artículo setup.py vs setup.cfg en Python .

Giorgos Myrianthous avatar Mar 07 '2022 19:03 Giorgos Myrianthous