Empecé a trabajar con Python. He añadido requirements.txt
y setup.py
a mi proyecto. Pero, todavía estoy confundido sobre el propósito de ambos archivos. He leído que setup.py
está diseñado para cosas redistribuibles y que requirements.txt
está 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?
Respuestas:
requirements.txt
Esto le ayuda a configurar su entorno de desarrollo. Programas como
pip
se pueden utilizar para instalar todos los paquetes enumerados en el archivo de una sola vez. Después de eso, puede comenzar a desarrollar su secuencia de comandos de Python. Especialmente útil si planea que otros contribuyan al desarrollo o utilicen entornos virtuales. Así es como se usa:setup.py
Esto le permite crear paquetes que puede redistribuir. Este script está destinado a instalar su paquete en el sistema del usuario final, no a preparar el entorno de desarrollo como
pip install -r requirements.txt
hace. Consulte esta respuesta para obtener más detalles sobre setup.py.Las dependencias de su proyecto se enumeran en ambos archivos.
fuente
La respuesta corta es que solo
requirements.txt
sirve para enumerar los requisitos del paquete.setup.py
por otro lado, es más como un script de instalación. Si no planea instalar el código de Python, normalmente solo necesitarárequirements.txt
.El archivo
setup.py
describe, además de las dependencias del paquete, el conjunto de archivos y módulos que deben empaquetarse (o compilarse, en el caso de los módulos nativos (es decir, escritos en C)) y los metadatos para agregar a las listas 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 conducir a un poco de duplicación. Lea a continuación para obtener más detalles.
requirements.txt
Este archivo enumera los requisitos del paquete de Python. Es un archivo de texto sin formato (opcionalmente con comentarios) que enumera las dependencias del paquete de su proyecto de Python (una por línea). Que no describen la manera en la que está instalado el paquete python. Por lo general, consumiría el archivo de requisitos con
pip install -r requirements.txt
.El nombre del archivo de texto es arbitrario, pero a menudo es
requirements.txt
por convención. Al explorar repositorios de código fuente de otros paquetes de Python, es posible que se encuentre con otros nombres, comodev-dependencies.txt
odependencies-dev.txt
. Aquellos tienen el mismo propósito que,dependencies.txt
pero 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ían todo el conjunto de dependencias del desarrollador para ejecutar el paquete.Si hay varias
requirements-X.txt
variantes, normalmente una enumerará las dependencias de tiempo de ejecución y la otra el tiempo de compilación o las dependencias de prueba. Algunos proyectos también conectan en cascada su archivo de requisitos, es decir, cuando un archivo de requisitos incluye otro archivo ( ejemplo ). Hacerlo puede reducir la repetición.setup.py
Este es un script de Python que usa el
setuptools
módulo para definir un paquete de Python (nombre, archivos incluidos, metadatos del paquete e instalación). Será, comorequirements.txt
, también la lista de ejecución dependencias del paquete. Setuptools es la forma de facto de construir e instalar paquetes de Python, pero tiene sus deficiencias, que con el tiempo han hecho surgir el desarrollo de nuevos "administradores de metapaquetes", como pip. Ejemplos de deficiencias de setuptools son su incapacidad para instalar múltiples 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
(opip install my-module
), pip se ejecutarásetup.py
en el directorio (o módulo) dado. De manera similar, cualquier módulo que tenga unsetup.py
se puedepip
instalar, por ejemplo, ejecutándolopip install .
desde la misma carpeta.¿Realmente necesito ambos?
La respuesta corta es no, pero es bueno tener ambos. Logran diferentes propósitos, pero ambos pueden usarse para enumerar sus dependencias.
Hay un truco que puede considerar para evitar duplicar su lista de dependencias entre
requirements.txt
ysetup.py
. Si ya ha escrito unsetup.py
paquete que funcione completamente y sus dependencias son en su mayoría externas, podría considerar tener un simplerequirements.txt
con solo lo siguiente:El
-e
es una especialpip install
opción que instala el paquete dado en editable modo. Cuandopip -r requirements.txt
se 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 en su lugar desde el repositorio sin reinstalarlo.También puede aprovechar lo que se llama "extras de setuptools" cuando tiene ambos archivos en su 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:
y luego, en el archivo de requisitos:
Esto mantendría todas sus listas de dependencias dentro de setup.py.
Nota : normalmente, ejecutaría pip y setup.py desde una caja de arena, como las creadas con el programa
virtualenv
. Esto evitará instalar paquetes de Python fuera del contexto del entorno de desarrollo de su proyecto.fuente
.
sin-e
adentrorequirements.txt
. Este método simplemente delega todos los requisitossetup.py
y no necesita forzar a nadie al modo editable. Los usuarios todavía pueden hacerlopip install -e .
si quieren.-e .
también usa setup.py para encontrar dependencias, pero vincula la carpeta actual (en su lugar, con un enlace simbólico) en la carpeta de instalación de pip, en lugar de tomar una copia;-e
generalmente lo usaría solo si está desarrollando el paquete. Con-e
, los cambios en los archivos de su paquete de Python (* .py) entrarían en vigencia inmediatamente en su entorno pip, en lugar de tener que forzar la reinstalación del paquete después de cada cambio.cd foo && pip install -r ./bar/requirements.txt
, ¿ buscará setup.py enfoo/bar
ofoo
? Si es lo último, ¿hay alguna manera de lograr lo primero?pip -r REQ
no le importa el directorio en el que está REQ. Se puede alimentar desde un FIFO incluso si lo desea:pip install -r <(echo "mylib1"; echo "mylib2";)
. ¿Dónde<(CMD)
está la sustitución del comando bash, no la redirección stdin?En aras de la integridad, así es como lo veo en
34 ángulos diferentes.Esta es la descripción precisa citada de la documentación oficial (el énfasis es mío):
Pero aún puede que no sea fácil de entender, por lo que en la siguiente sección, se incluyen 2 ejemplos fácticos para demostrar cómo se supone que los 2 enfoques deben usarse de manera diferente.
Por lo tanto, sus usos reales son (se supone que son) diferentes
Si su proyecto
foo
va a ser lanzado como una biblioteca independiente (es decir, otros probablemente lo haríanimport foo
), entonces usted (y sus usuarios posteriores) querrían tener una declaración flexible de dependencia, de modo que su biblioteca no lo haría (y no debe ) Sea "quisquilloso" acerca de la versión exacta de SUS dependencias. Entonces, típicamente, su setup.py contendría líneas como esta:Si solo desea "documentar" o "fijar" de alguna manera su entorno EXACTO actual para su aplicación
bar
, es decir, usted o sus usuarios desearían usar su aplicaciónbar
tal como está, es decirpython bar.py
, ejecutándose , 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í:En realidad, ¿cuál uso?
Si está desarrollando una aplicación
bar
que será utilizada porpython bar.py
, incluso si es "solo un script por diversión", se le recomienda que use requirements.txt porque, quién sabe, la próxima semana (que es Navidad) recibirá un una computadora nueva como regalo, por lo que necesitaría configurar su entorno exacto allí nuevamente.Si está desarrollando una biblioteca
foo
que será utilizada porimport foo
, debe preparar un setup.py. Período. Pero aún puede optar por proporcionar un requirements.txt al mismo tiempo, que puede:(a) estar en el
A==1.2.3
estilo (como se explica en el # 2 arriba);(b) o simplemente contener un sencillo mágico
.
que equivaldría aproximadamente a "instalar los requisitos basados en setup.py" sin duplicación. Personalmente, considero que este último enfoque desdibuja la línea, aumenta la confusión y NO agrega realmente valor, pero no obstante, es un truco derivado de un enfoque mencionado por el mantenedor de paquetes de Python, Donald, en su publicación de blog .
Diferentes límites inferiores.
Incluso después de haber seguido los 3 criterios anteriores y haber decidido correctamente que su biblioteca
hybrid-engine
usaría asetup.py
para declarar su dependenciaengine>=1.2.0
, y su aplicación de muestrareliable-car
usaríarequirements.txt
para declarar su dependenciaengine>=1.2.3
, aunque la última versión deengine
ya está en 1.4.0. Como puede ver, su elección para su número límite inferior sigue siendo sutilmente diferente. Y he aquí por qué.hybrid-engine
depende deengine>=1.2.0
porque, hipotéticamente hablando, la capacidad necesaria de "combustión interna" se introdujo por primera vez enengine 1.2.0
, y esa capacidad es la necesidad dehybrid-engine
, independientemente de si podría haber algunos errores (menores) dentro de dicha versión y se corrigió en versiones posteriores 1.2.1 , 1.2.2 y 1.2.3.reliable-car
depende deengine>=1.2.3
porque esa es la versión más antigua SIN problemas conocidos, hasta ahora. Seguro que hay nuevas capacidades en versiones posteriores, digamos, "motor eléctrico" introducidoengine 1.3.0
y "reactor nuclear" introducidoengine 1.4.0
, pero no son necesarios para el proyectoreliable-car
.fuente
A==1.2.3
, y luego si el paquete posterior de su biblioteca depende deA==1.2.4
, ahora no habrá una manera de satisfacer ambos. La solución para minimizar este conflicto es que su biblioteca defina un rango que sabe que funcionaría. Suponiendo que muchas bibliotecas ascendentes ya siguen a semver.org ,A>=1,<2
funcionaría.foo
noimport foo
le dará? Esa respuesta hacky aceptada en ese enlace que proporcionó sirve como un ejemplo perfecto de por qué el encargado del paquete "no debe ni debe ser exigente". :-) ¿Ahora puedo darme tu voto a favor?