¿Cómo podría obtener la versión definida en setup.py
mi paquete (para --version
u otros fines)?
python
setuptools
elmarco
fuente
fuente
Respuestas:
Cadena de versión de interrogación de distribución ya instalada
Para recuperar la versión desde el interior de su paquete en tiempo de ejecución (lo que parece estar preguntando realmente), puede usar:
Almacene la cadena de versión para usar durante la instalación
Si desea ir al revés (que parece ser lo que otros autores de respuestas aquí parecen haber pensado que estaba preguntando), coloque la cadena de versión en un archivo separado y lea el contenido de ese archivo
setup.py
.Puede hacer una versión.py en su paquete con una
__version__
línea, luego leerla desde setup.py usandoexecfile('mypackage/version.py')
, para que se establezca__version__
en el espacio de nombres setup.py.Si desea una forma mucho más simple que funcione con todas las versiones de Python e incluso con lenguajes que no sean de Python que puedan necesitar acceso a la cadena de versión:
Almacene la cadena de versión como el único contenido de un archivo de texto plano, llamado eg
VERSION
, y lea ese archivo durantesetup.py
.El mismo
VERSION
archivo funcionará exactamente igual en cualquier otro programa, incluso los que no sean Python, y solo necesita cambiar la cadena de versión en un lugar para todos los programas.Advertencia sobre la condición de carrera durante la instalación
Por cierto, NO importe su paquete desde su setup.py como se sugiere en otra respuesta aquí: parecerá funcionar para usted (porque ya tiene instaladas las dependencias de su paquete), pero causará estragos en los nuevos usuarios de su paquete , ya que no podrán instalar su paquete sin instalar primero manualmente las dependencias.
fuente
execfile
funciona muy bien ... pero (lamentablemente) no funciona con Python 3.with open('mypackage/version.py') as f: exec(f.read())
en lugar deexecfile('mypackage/version.py')
. (De stackoverflow.com/a/437857/647002 )estudio de ejemplo:
mymodule
Imagina esta configuración:
Luego imagine un escenario habitual en el que tenga dependencias y se
setup.py
vea así:Y un ejemplo
__init__.py
:Y por ejemplo
myclasses.py
:problema # 1: importar
mymodule
durante la configuraciónSi sus
setup.py
importaciones,mymodule
entonces durante la configuración , probablemente obtendrá unImportError
. Este es un error muy común cuando su paquete tiene dependencias. Si su paquete no tiene otras dependencias que las incorporadas, puede estar seguro; Sin embargo, esta no es una buena práctica. La razón de esto es que no es a prueba de futuro; diga mañana que su código necesita consumir alguna otra dependencia.problema # 2: ¿dónde está mi
__version__
?Si hardcode
__version__
desetup.py
entonces puede no coincidir con la versión que le enviará en su módulo. Para ser coherente, lo pondría en un lugar y lo leería desde el mismo lugar cuando lo necesite. Alimport
usarlo puede obtener el problema # 1.solución: à la
setuptools
Se podría utilizar una combinación de
open
,exec
y proporcionar un diccionario paraexec
las variables add:Y en
mymodule/version.py
exponer la versión:De esta manera, la versión se envía con el módulo, y no tiene problemas durante la instalación al intentar importar un módulo que tiene dependencias faltantes (aún no se ha instalado).
fuente
La mejor técnica es definir
__version__
en el código de su producto, luego importarlo en setup.py desde allí. Esto le da un valor que puede leer en su módulo en ejecución, y solo tiene un lugar para definirlo.Los valores en setup.py no están instalados y setup.py no se queda después de la instalación.
Lo que hice (por ejemplo) en coverage.py:
ACTUALIZACIÓN (2017): coverage.py ya no se importa para obtener la versión. Importar su propio código puede hacer que sea desinstalable, porque su código de producto intentará importar dependencias, que aún no están instaladas, porque setup.py es lo que las instala.
fuente
__version__
que contiene está roto de alguna manera, su importación también se romperá. Python no sabe cómo interpretar solo las declaraciones que desea. @pjeby tiene razón: si su módulo necesita importar otros módulos, es posible que aún no estén instalados y será caótico. Esta técnica funciona si tiene cuidado de que la importación no genere una larga cadena de otras importaciones.pip install <packagename>
, me sale el siguiente error:ImportError: No module named <packagename>
. ¡AVISE a sus lectores que no puede ejecutar archivos setup.py como este en entornos donde el paquete no está instalado!Su pregunta es un poco vaga, pero creo que lo que está preguntando es cómo especificarla.
Necesita definir
__version__
así:Y luego puede confirmar que setup.py conoce la versión que acaba de especificar:
fuente
No estaba contento con estas respuestas ... no quería requerir herramientas de configuración, ni crear un módulo completamente separado para una sola variable, así que se me ocurrió esto.
Para cuando esté seguro de que el módulo principal está en estilo pep8 y seguirá así:
Si desea ser más cuidadoso y usar un analizador real:
setup.py es algo así como un módulo desechable, así que no es un problema si es un poco feo.
Actualización: Es muy gracioso porque me he alejado de esto en los últimos años y comenzó a usar un archivo separado en el paquete de llamada
meta.py
. Puse muchos metadatos allí que quizás quiera cambiar con frecuencia. Entonces, no solo por un valor.fuente
ast.get_docstring()
con algunos.split('\n')[0].strip()
etc. para completar automáticamentedescription
desde la fuente. Una cosa menos para mantener sincronizadoCree un archivo en su árbol de origen, por ejemplo, en su base de datos / su paquete / _version.py. Deje que el archivo contenga una sola línea de código, como esta:
__version__ = "1.1.0-r4704"
Luego, en su setup.py, abra ese archivo y analice el número de versión de esta manera:
Finalmente, en
yourbasedir/yourpackage/__init__.py
import _version así:Un ejemplo de código que hace esto es el paquete "pyutil" que mantengo. (Consulte PyPI o búsqueda de google: stackoverflow no me permite incluir un hipervínculo en esta respuesta).
@pjeby tiene razón en que no debe importar su paquete desde su propio setup.py. Eso funcionará cuando lo pruebe creando un nuevo intérprete de Python y ejecutando setup.py en primer lugar:
python setup.py
pero hay casos en que no funcionará. Esto se debe aimport youpackage
que no significa leer el directorio de trabajo actual para un directorio llamado "yourpackage", significa buscar en la actualsys.modules
una clave "yourpackage" y luego hacer varias cosas si no está allí. Por lo tanto, siempre funciona cuando lo hacepython setup.py
porque tiene un nuevo, vacíosys.modules
, pero esto no funciona en general.Por ejemplo, ¿qué sucede si py2exe está ejecutando su setup.py como parte del proceso de empaquetar una aplicación? He visto un caso como este donde py2exe pondría el número de versión incorrecto en un paquete porque el paquete estaba obteniendo su número de versión de
import myownthing
en su setup.py, pero anteriormente se había importado una versión diferente de ese paquete durante la ejecución de py2exe. Del mismo modo, ¿qué sucede si setuptools, easy_install, distribution o distutils2 intentan construir su paquete como parte de un proceso de instalación de un paquete diferente que depende del suyo? Luego, si su paquete es importante en el momento en que se está evaluando su setup.py, o si ya hay una versión de su paquete que se importó durante la vida de este intérprete de Python, o si la importación de su paquete requiere la instalación de otros paquetes primero , o tiene efectos secundarios, puede cambiar los resultados. He tenido varias dificultades para tratar de reutilizar los paquetes de Python que causaron problemas para herramientas como py2exe y setuptools porque su setup.py importa el paquete para encontrar su número de versión.Por cierto, esta técnica funciona muy bien con herramientas para crear automáticamente el
yourpackage/_version.py
archivo para usted, por ejemplo, leyendo su historial de control de revisiones y escribiendo un número de versión basado en la etiqueta más reciente en el historial de control de revisiones. Aquí hay una herramienta que hace eso para darcs: http://tahoe-lafs.org/trac/darcsver/browser/trunk/README.rst y aquí hay un fragmento de código que hace lo mismo para git: http: // github .com / warner / python-ecdsa / blob / 0ed702a9d4057ecf33eea969b8cf280eaccd89a1 / setup.py # L34fuente
Esto también debería funcionar, utilizando expresiones regulares y dependiendo de los campos de metadatos para tener un formato como este:
Use lo siguiente al comienzo de su setup.py:
Después de eso, puede usar los metadatos en su script de esta manera:
fuente
Con una estructura como esta:
donde version.py contiene:
Puedes hacer esto en setup.py :
Esto no causará ningún problema con las dependencias que tenga en su mymodule / __ init__.py
fuente
Para evitar importar un archivo (y así ejecutar su código), uno podría analizarlo y recuperar el
version
atributo del árbol de sintaxis:Este código intenta encontrar la asignación
__version__
oVERSION
en el nivel superior del retorno del módulo es el valor de cadena. El lado derecho puede ser una cadena o una tupla.fuente
Hay mil maneras de pelar un gato, aquí está el mío:
fuente
Limpieza https://stackoverflow.com/a/12413800 de @ gringo-suave:
fuente
Ahora, esto es asqueroso y necesita un poco de refinamiento (incluso puede haber una llamada de miembro descubierta en pkg_resources que me perdí), pero simplemente no veo por qué esto no funciona, ni por qué nadie lo ha sugerido hasta la fecha (Googlear ha no subió esto) ... tenga en cuenta que esto es Python 2.x, y requeriría requerir pkg_resources (suspiro):
fuente
Quisimos poner la meta información sobre nuestro paquete
pypackagery
en__init__.py
, pero no pudo ya que cuenta con dependencias de terceros como PJ Eby ya se ha señalado (véase su respuesta y la advertencia con respecto a la condición de carrera).Lo resolvimos creando un módulo separado
pypackagery_meta.py
que contiene solo la metainformación:luego importó la metainformación en
packagery/__init__.py
:y finalmente lo usé en
setup.py
:Debe incluir
pypackagery_meta
en su paquete conpy_modules
el argumento de configuración. De lo contrario, no puede importarlo durante la instalación, ya que la distribución empaquetada carecería de él.fuente
Simple y directo, cree un archivo llamado
source/package_name/version.py
con los siguientes contenidos:Luego, en su archivo
source/package_name/__init__.py
, importa la versión para que otras personas la usen:Ahora puedes poner esto
setup.py
Probado esto con Python
2.7
,3.3
,3.4
,3.5
,3.6
y3.7
en Linux, Windows y Mac OS. Utilicé en mi paquete que tiene pruebas de integración y unidad para todas estas plataformas. Puedes ver los resultados desde.travis.yml
yappveyor.yml
aquí:Una versión alternativa está usando el administrador de contexto:
También puede usar el
codecs
módulo para manejar errores unicode tanto en Python2.7
como en3.6
Si está escribiendo un módulo Python al 100% en C / C ++ usando Extensiones Python C, puede hacer lo mismo, pero usando C / C ++ en lugar de Python.
En este caso, cree lo siguiente
setup.py
:Que lee la versión del archivo
version.h
:Pero, no olvide crear el
MANIFEST.in
para incluir elversion.h
archivo:Y está integrado en la aplicación principal con:
Referencias
fuente
Implemente el paquete en el servidor y la convención de nomenclatura de archivos para paquetes de índices:
ejemplo para la conversión de versión dinámica de pip:
ganar:
Mac:
Encuentre el ejemplo setup.py llama a la versión de pip dinámica que coincide con git commit
fuente
Estoy usando una variable de entorno como la siguiente
VERSIÓN = 0.0.0 python setup.py sdist bdist_wheel
En setup.py
Para verificar la coherencia con la versión del empaquetador, estoy usando el siguiente script.
fuente