Tengo un requirements.txt
archivo que estoy usando con Travis-CI. Parece tonto duplicar los requisitos en ambos requirements.txt
y setup.py
, por lo tanto, esperaba pasar un identificador de archivo al install_requires
kwarg setuptools.setup
.
es posible? Si es así, ¿cómo debo hacerlo?
Aquí está mi requirements.txt
archivo:
guessit>=0.5.2
tvdb_api>=1.8.2
hachoir-metadata>=1.3.3
hachoir-core>=1.3.3
hachoir-parser>=1.3.4
install_requires
se usa para declarar dependencias en los paquetes que son necesarios para que el paquete funcione y los usa el desarrollador del paquete, mientras querequirements.txt
se usa para automatizar la instalación de entornos, lo que permite instalar software adicional y anclar la versión y los administradores de sistemas los usan paquete. Su rol y público objetivo difieren significativamente, por lo que tratar de combinarlos como lo desea OP es un verdadero error de diseño en mi humilde opinión.[line.strip() for line in open("requirements.txt").readlines()]
?pkg_resources.parse_requirements()
Respuestas:
Puede darle la vuelta y enumerar las dependencias
setup.py
y tener un solo carácter, un punto.
, en surequirements.txt
lugar.Alternativamente, incluso si no se recomienda, aún es posible analizar el
requirements.txt
archivo (si no hace referencia a ningún requisito externo por URL) con el siguiente truco (probado conpip 9.0.1
):Sin embargo, esto no filtra los marcadores del entorno .
En versiones antiguas de pip, más específicamente anteriores a 6.0 , hay una API pública que se puede utilizar para lograr esto. Un archivo de requisitos puede contener comentarios (
#
) y puede incluir algunos otros archivos (--requirement
o-r
). Por lo tanto, si realmente desea analizar unrequirements.txt
puede usar el analizador de pip:fuente
setup(..., dependency_links=[str(req_line.url) for req_line in parse_requirements(<requirements_path>)], ...)
pip
defecto, se analizan las dependenciassetup.py
en ausencia derequirements.txt
, la respuesta simple que Tobu señala astutamente a continuación es enumerar todas las dependenciassetup.py
y eliminarlasrequirements.txt
. Para las aplicaciones que requieren ambos, simplemente reduzca la lista de dependenciasrequirements.txt
simplemente al.
carácter. Hecho.En vista de ello, parece que
requirements.txt
ysetup.py
son duplicados tontas, pero es importante entender que mientras que la forma es similar, la función prevista es muy diferente.El objetivo del autor de un paquete, al especificar dependencias, es decir "donde sea que instale este paquete, estos son los otros paquetes que necesita para que este paquete funcione".
Por el contrario, el autor de la implementación (que puede ser la misma persona en un momento diferente) tiene un trabajo diferente, ya que dice "aquí está la lista de paquetes que hemos reunido y probado y que ahora necesito instalar".
El autor del paquete escribe para una amplia variedad de escenarios, porque están poniendo su trabajo ahí fuera para que lo usen de formas que quizás no conozcan, y no tienen forma de saber qué paquetes se instalarán junto con su paquete. Para ser un buen vecino y evitar conflictos de versiones de dependencia con otros paquetes, necesitan especificar una gama tan amplia de versiones de dependencia como pueda funcionar. Esto es lo que
install_requires
ensetup.py
sí.El autor de la implementación escribe para un objetivo muy diferente y muy específico: una única instancia de una aplicación o servicio instalado, instalado en una computadora en particular. Para controlar con precisión una implementación y asegurarse de que los paquetes correctos se prueben e implementen, el autor de la implementación debe especificar la versión exacta y la ubicación de origen de cada paquete que se instalará, incluidas las dependencias y las dependencias de la dependencia. Con esta especificación, una implementación se puede aplicar repetidamente a varias máquinas, o probarse en una máquina de prueba, y el autor de la implementación puede estar seguro de que los mismos paquetes se implementan cada vez. Esto es lo que
requirements.txt
hace.Entonces puede ver que, si bien ambos parecen una gran lista de paquetes y versiones, estas dos cosas tienen trabajos muy diferentes. ¡Y definitivamente es fácil mezclar esto y equivocarse! Pero la forma correcta de pensar en esto es que
requirements.txt
es una "respuesta" a la "pregunta" planteada por los requisitos en todos los diversossetup.py
archivos de paquete. En lugar de escribirlo a mano, a menudo se genera diciéndole a pip que mire todos lossetup.py
archivos en un conjunto de paquetes deseados, encuentre un conjunto de paquetes que considere que cumple con todos los requisitos y luego, una vez instalados, "congele "esa lista de paquetes en un archivo de texto (de aquípip freeze
proviene el nombre).Entonces la comida para llevar:
setup.py
debería declarar las versiones de dependencia más flojas posibles que aún sean viables. Su trabajo es decir con qué puede funcionar un paquete en particular.requirements.txt
es un manifiesto de implementación que define un trabajo de instalación completo y no debe considerarse vinculado a ningún paquete. Su trabajo es declarar una lista exhaustiva de todos los paquetes necesarios para que una implementación funcione.Referencias
fuente
requirements.txt
junto con la fuente del paquete que contiene los requisitos concretos / congelados para la instalación o prueba. ¿Seguramentesetup.py
puede usarse para este propósito dentro del proyecto mismo? Solo puedo imaginar el uso de un archivo de este tipo para herramientas utilizadas para apoyar la gestión del proyecto (por ejemplo, refactorización, lanzamiento, etc.).requirements.txt
hay más documentación para el estado del mundo que produjo una compilación determinada, a pesar de que generalmente no se usa en el proceso de compilación en sí? Eso tiene sentido. Sin embargo, parece que varios sistemas dependen de la duplicación: Travis instala algunos paquetes predeterminados (antiguos) en su virtualenv y dice que los userequirements.txt
. Si pregunto cómo garantizar que las dependencias se utilicen a más tardarsetup.py
, la gente insiste en que debería usarlasrequirements.txt
.No puede tomar un identificador de archivo. El
install_requires
argumento solo puede ser una cadena o una lista de cadenas .Por supuesto, puede leer su archivo en el script de configuración y pasarlo como una lista de cadenas a
install_requires
.fuente
install_requires
. Sin embargo, no funciona si no utiliza la sintaxis declarativa.setup.py
es un programa que debería ejecutarse, no un archivo de datos que debería analizarse. Eso no empeora esta respuesta.include requirements.txt
en suMANIFEST.in
o no podrá instalar su biblioteca desde una distribución fuente.Los archivos de requisitos usan un formato de pip expandido, que solo es útil si necesita complementarlo
setup.py
con restricciones más fuertes, por ejemplo, especificando las URL exactas de las que deben proceder algunas de las dependencias, o la salida depip freeze
congelar todo el conjunto de paquetes a trabajo conocido versiones. Si no necesita restricciones adicionales, use solo asetup.py
. Si siente que realmente necesita enviar unrequirements.txt
correo electrónico de todos modos, puede hacerlo en una sola línea:Será válido y se referirá exactamente al contenido del
setup.py
que está en el mismo directorio.fuente
pip install -r requirements.txt
) sin instalar el paquete en sí?-e .
debería ser suficiente. Consulte esta página: caremad.io/posts/2013/07/setup-vs-requirementSi bien no es una respuesta exacta a la pregunta, recomiendo la publicación del blog de Donald Stufft en https://caremad.io/2013/07/setup-vs-requirement/ para una buena interpretación de este problema. Lo he estado usando con gran éxito.
En resumen,
requirements.txt
no es unasetup.py
alternativa, sino un complemento de implementación. Mantenga una abstracción adecuada de las dependencias del paquete ensetup.py
. Configurerequirements.txt
o más de ellos para obtener versiones específicas de dependencias de paquetes para desarrollo, prueba o producción.Por ejemplo, con los paquetes incluidos en el repositorio bajo
deps/
:pip ejecuta paquetes
setup.py
e instala las versiones específicas de dependencias declaradas eninstall_requires
. No hay duplicidad y se preserva el propósito de ambos artefactos.fuente
pip install my-package
. Si las dependencias de my-package no se enumeran en my-package / setup.py, no las instalapip install my-package
. No he podido determinar cómo proporcionar un paquete para otros que incluya dependencias sin indicarlo explícitamente en setup.py. Me encantaría saber si alguien ha descubierto cómo mantenerlo SECO mientras permite que otros instalen las dependencias my-package + sin descargar el archivo de requisitos y llamar manualmentepip install -r my-package/requirements.txt
.requirements.txt
. Ese es todo el punto. Se actualizó la pregunta para aclarar las cosas. También se actualizó el enlace de publicación de blog obsoleto.El uso
parse_requirements
es problemático porque la API de pip no está documentada y soportada públicamente. En el pip 1.6, esa función en realidad se está moviendo, por lo que es probable que los usos existentes se rompan.Una forma más confiable de eliminar la duplicación entre
setup.py
yrequirements.txt
es especificar sus dependenciassetup.py
y luego ponerlas-e .
en surequirements.txt
archivo.pip
Aquí encontrará información de uno de los desarrolladores sobre por qué es una mejor manera de hacerlo: https://caremad.io/blog/setup-vs-requirement/fuente
La mayoría de las otras respuestas anteriores no funcionan con la versión actual de la API de pip. Aquí está la forma correcta * de hacerlo con la versión actual de pip (6.0.8 en el momento de la escritura, también funcionaba en 7.1.2. Puede verificar su versión con pip -V).
* Correcto, ya que es la forma de usar parse_requirements con el pip actual. Probablemente todavía no sea la mejor manera de hacerlo, ya que, como decían los carteles anteriores, pip realmente no mantiene una API.
fuente
Instale el paquete actual en Travis. Esto evita el uso de un
requirements.txt
archivo. Por ejemplo:fuente
pip freeze
y exporte ese archivo a algún lugar como un artefacto (como S3 o algo así), entonces tendría una excelente manera de instalar repetidamente exactamente lo que probadofrom pip.req import parse_requirements
no funcionó para mí y creo que es para las líneas en blanco en mis requerimientos.txt, pero esta función sí funcionafuente
Si no desea obligar a sus usuarios a instalar pip, puede emular su comportamiento con esto:
fuente
La siguiente interfaz quedó obsoleta en pip 10:
Así que lo cambié a un simple análisis de texto:
fuente
pathlib
variación de la misma.Este enfoque simple lee el archivo de requisitos de
setup.py
. Es una variación de la respuesta de Dmitiry S. .. Esta respuesta es compatible solo con Python 3.6+.Por DS ,
requirements.txt
puede documentar requisitos concretos con números de versión específicos, mientras quesetup.py
puede documentar requisitos abstractos con rangos de versiones sueltas.A continuación hay un extracto de mi
setup.py
.Tenga en cuenta que
distutils.text_file.TextFile
eliminará los comentarios. Además, según mi experiencia, aparentemente no es necesario que realice ningún paso especial para agrupar el archivo de requisitos.fuente
¡CUIDADO CON EL
parse_requirements
COMPORTAMIENTO!Tenga en cuenta que
pip.req.parse_requirements
cambiará los guiones bajos a guiones. Esto me enfureció durante unos días antes de descubrirlo. Ejemplo que demuestra:produce
fuente
[ir.req.unsafe_name for ir in req_deps if ir.req is not None]
Creé una función reutilizable para esto. En realidad, analiza un directorio completo de archivos de requisitos y los establece en extras_require.
Lo último siempre disponible aquí: https://gist.github.com/akatrevorjay/293c26fefa24a7b812f5
fuente
pip._internal
... Si no proporciona una API externa utilizable, entonces no debería romper todos esos que están usando todo lo que proporcionas.Otra posible solución ...
y luego usar ...
fuente
tree
vieneNo recomendaría hacer tal cosa. Como se mencionó varias veces
install_requires
yrequirements.txt
definitivamente no se supone que sea la misma lista. Pero dado que hay muchas respuestas engañosas que involucran API privadas internas de pip , podría valer la pena buscar alternativas más sensatas ...No es necesario que pip analice un
requirements.txt
archivo desde un script setuptoolssetup.py
. El proyecto setuptools ya contiene todas las herramientas necesarias en su paquete de nivel superiorpkg_resources
.Podría verse más o menos así:
fuente
pip
el análisis y nopkg_resources
desde antes de 2015 son errores como github.com/pypa/setuptools/issues/470 . Esta exacta está arreglada hoy en día, pero todavía tengo un poco de miedo de usarla, ya que ambas implementaciones parecen estar desarrolladas por separado.Cruce la publicación de mi respuesta de esta pregunta SO para otra solución simple de prueba de versión pip.
Luego, solo incluya todos sus requisitos en el
requirements.txt
directorio raíz del proyecto.fuente
Hice esto:
fuente
Otro
parse_requirements
truco que también analiza los marcadores ambientales enextras_require
:Debería admitir discos sdist y binarios.
Según lo declarado por otros,
parse_requirements
tiene varias deficiencias, por lo que esto no es lo que debe hacer en proyectos públicos, pero puede ser suficiente para proyectos internos / personales.fuente
parse_requirements()
, por lo que ahora falla.Aquí hay un truco completo (probado con
pip 9.0.1
) basado en la respuesta de Romain que lo analizarequirements.txt
y filtra de acuerdo con los marcadores actuales del entorno :fuente
r.match_markers()
, en realidad está evaluando los marcadores, que es lo correcto para un sdist. Sin embargo, si está compilando un dist binario (por ejemplo, wheel), el paquete solo enumerará las bibliotecas que coinciden con su entorno de tiempo de compilación.wheel environment
(si es lo que la persona intenta hacer) para evaluar los marcadores en su contra?bdist_wheel
. No evalúa los marcadores, solo los agregaextras_require
.