Comment puis-je obtenir la version définie dans setup.py (setuptools) dans mon colis?
Comment pourrais-je obtenir la version définie dans setup.py
de mon colis (pour --version
, ou à d'autres fins)?
- Je pense que c'est à peu près la même question que stackoverflow.com/questions/458550/... .
Vous devez vous connecter pour publier un commentaire.
Interroger chaîne de version déjà installée de distribution
Pour récupérer la version de l'intérieur de votre colis au moment de l'exécution (ce que votre question semble effectivement être la demande), vous pouvez utiliser:
Magasin de chaîne de version pour une utilisation lors de l'installation
Si vous voulez aller ronds dans l'autre sens (ce qui semble être ce que les autres répondre à des auteurs ici semblent avoir pensé que vous étiez la demande), mettre la chaîne de version dans un fichier séparé et de lire ce fichier est contenu dans
setup.py
.Vous pourriez faire une version.py dans votre colis avec un
__version__
ligne, puis le lire à partir de setup.py à l'aide deexecfile('mypackage/version.py')
, de sorte qu'il établit__version__
dans le setup.py espace de noms.Si vous voulez un moyen beaucoup plus simple qui fonctionne avec toutes les versions de Python, et même les non-Python langues qui peuvent avoir besoin d'accéder à la chaîne de version:
Magasin de la chaîne de version que le seul contenu d'un fichier texte, nommé par exemple
VERSION
, et de lire le fichier en cours desetup.py
.La même
VERSION
fichier sera alors exactement comme vous le bien dans n'importe quel autre programme, même les non-Python, et vous avez seulement besoin de changer la chaîne de la version en un seul endroit pour tous les programmes.Avertissement au sujet de la race condition lors de l'installation
Par le chemin, NE PAS importer votre colis auprès de votre setup.py comme suggéré dans une autre réponse ici: il semble travailler pour vous (parce que vous avez déjà les dépendances de votre paquet installé), mais il va faire des ravages sur les nouveaux utilisateurs de votre colis, car ils ne seront pas en mesure d'installer le paquet sans installation manuelle du d'abord les dépendances.
execfile
fonctionne vraiment bien... mais (malheureusement) ne fonctionne pas avec Python 3.with open('mypackage/version.py') as f: exec(f.read())
en place deexecfile('mypackage/version.py')
. (À partir de stackoverflow.com/a/437857/647002)__version__
approche n'est pas compatible avec setuptools-scm, regretably. Lepkg_resources
approche est assez bonne, mais il ne pourra pas terriblement bien que l'élaboration d'un ensemble (puisqu'il n'est pas installé).__version__
est effectivement importées. Eh bien, c'est de plus un problème sur l'IDE côté, mais il est.mypackage/VERSION
fichier. J'aimerais être capable de se déplacer queVERSION
fichier à la racine de la source, donc mon build scripts n'ont pas besoin de connaître le nom du package. Aussi, mon développeur serait libre avec leur structure de dossier et je ne voudrais avoir à traiter avec " trait de soulignement vs dash questions: e.g: mon colis est un nom valide pour le paquet, mais pas pour le dossier.print(pkg_resources.get_distribution(MYPACKAGE))
plutôt queprint("%s %s" % (MYPACKAGE, pkg_resources.require(MYPACKAGE)[0].version))
exemple d'étude:
mymodule
Imaginer cette configuration:
Alors imaginez un scénario où vous avez des dépendances et
setup.py
ressemble:Et un exemple
__init__.py
:Et par exemple
myclasses.py
:le problème n ° 1: importation de
mymodule
lors de l'installationSi votre
setup.py
importationsmymodule
puis lors de l'installation vous serait le plus susceptible d'obtenir unImportError
. C'est une erreur très commune lorsque votre colis a des dépendances. Si votre colis n'ont pas d'autres dépendances que les objets internes, vous pouvez être sûr; mais ce n'est pas une bonne pratique. La raison pour cela est qu'il n'est pas de l'avenir; dire demain, votre code doit consommer certains autres dépendances.problème #2: où est mon
__version__
?Si vous coder en dur
__version__
danssetup.py
alors il peut ne pas correspondre à la version que vous serait livré dans votre module. Pour être cohérent, vous le mettez dans un endroit et de le lire à partir de la même place quand vous en avez besoin. À l'aide deimport
vous pouvez obtenir le problème n ° 1.solution: à la
setuptools
Vous devez utiliser une combinaison de
open
,exec
et de fournir un dict pourexec
pour ajouter des variables:Et dans
mymodule/version.py
exposer la version:De cette façon, la version est livré avec le module, et vous n'avez pas de problèmes lors de l'installation d'essayer d'importer un module de dépendances manquantes (pas encore installé).
La meilleure technique est de définir
__version__
dans votre code de produit, puis l'importer dans setup.py à partir de là. Cela vous donne une valeur que vous pouvez lire dans votre module en cours d'exécution, et ont un seul lieu de le définir.Les valeurs dans setup.py ne sont pas installés, et setup.py ne pas rester dans les parages après l'installation.
Ce que j'ai fait (par exemple) dans coverage.py:
Mise à JOUR (2017): coverage.py n'importe plus pour avoir la version. L'importation de votre propre code peut rendre instables, parce que vous code produit vous essayez d'importer des dépendances, qui ne sont pas encore installé, parce que setup.py est ce que les installe.
__version__
dans ce qui est cassé, d'une certaine façon, votre importation sera aussi brisée. Python ne sait pas seulement interpréter les instructions que vous voulez. @pjeby est juste: si votre module doit importer d'autres modules, ils ont peut-être pas encore installé, et il sera chaotique. Cette technique fonctionne si vous êtes attentif à ce que l'import n'est pas caues de la longue chaîne des autres importations.pip install <packagename>
, j'obtiens l'erreur suivante:ImportError: No module named <packagename>
. Veuillez AVERTIR vos lecteurs que vous ne pouvez pas exécuter setup.py les fichiers de ce genre sur les environnements où le paquet n'est pas déjà installée!setup()
appel.mypackage/__init__.py
d'être en mesure d'importer toutes les dépendances. La réponse devrait être mis à jour pour montrer comment le faire correctement (par exemple, mettre un distinctversion.py
module, puis de les importer à partir de__init__.py
), de sorte que les gens n'ont pas tort de copier les codes périmés ici.Votre question est un peu vague, mais je pense que ce que vous demandez est de savoir comment le spécifier.
Vous devez définir
__version__
comme suit:Et ensuite, vous pouvez confirmer que setup.py sait à propos de la version que vous venez de spécifier:
Je n'étais pas heureux avec ces réponses... ne voulais pas besoin setuptools, ni faire tout un module séparé pour une seule variable, alors je suis venu avec ces.
Pour quand vous êtes sûr que le module principal est dans pep8 de style et de rester de cette façon:
Si vous voulez être très prudent et utiliser un vrai analyseur:
setup.py est un peu laissé de côté module, donc pas un problème si elle est un peu moche.
ast.get_docstring()
avec certains.split('\n')[0].strip()
etc de remplir automatiquement lesdescription
à partir de la source. Une chose de moins à conserver la synchronisationDe créer un fichier dans l'arborescence des sources, par exemple dans yourbasedir/yourpackage/_version.py . Laissez ce fichier ne contient qu'une seule ligne de code, comme ceci:
__version__ = "1.1.0-r4704"
Puis dans votre setup.py, ouvrez ce fichier et d'analyser le numéro de version comme ceci:
Enfin, dans
yourbasedir/yourpackage/__init__.py
importation _version comme ceci:Un exemple de code qui fait ce est le "pyutil" paquet que je maintiens. (Voir PyPI ou de recherche de google -- stackoverflow est me refusant d'inclure un lien hypertexte dans cette réponse.)
@pjeby est juste que vous ne devriez pas importer votre colis à partir de ses propres setup.py. Qui va travailler quand vous le tester en créant un nouvel interpréteur Python et de l'exécution de setup.py dans la première chose:
python setup.py
, mais il ya des cas où ça ne marchera pas. C'est parce queimport youpackage
ne signifie pas pour lire le répertoire de travail courant pour un répertoire nommé "yourpackage", il signifie regarder dans le courantsys.modules
pour une clé "yourpackage" et ensuite de faire différentes choses, si elle n'est pas là. De sorte qu'il fonctionne toujours lorsque vous nepython setup.py
parce que vous avez une nouvelle, videsys.modules
, mais cela ne fonctionne pas en général.Par exemple, si py2exe est de l'exécution de votre setup.py dans le cadre du processus de empaquetage d'une application? J'ai vu un cas comme ça où py2exe aurait mis le mauvais numéro de version sur un paquet parce que le paquet a été d'obtenir son numéro de version de
import myownthing
dans son setup.py mais une autre version de ce paquet avait déjà été importées au cours de la py2exe exécuter. De même, si setuptools, easy_install, distribuer, ou distutils2 est d'essayer de construire votre paquet dans le cadre d'un processus d'installation d'un package différent qui dépend de la vôtre? Alors que votre paquet est importable au moment de son setup.py est en cours d'évaluation, ou s'il existe déjà une version de votre colis qui a été importé au cours de cette interpréteur Python la vie, ou si l'importation de votre package requiert d'autres paquets à installer en premier, ou a des effets secondaires, peuvent modifier les résultats. J'ai eu plusieurs luttes à essayer de ré-utiliser les paquets Python qui a causé des problèmes pour les outils comme py2exe et setuptools parce que leur setup.py les importations de l'emballage lui-même afin de trouver son numéro de version.Par ailleurs, cette technique joue bien avec les outils de création automatique de la
yourpackage/_version.py
fichier pour vous, par exemple par la lecture de votre contrôle de révision de l'histoire et de la rédaction d'un numéro de version sur la base des plus récentes balise dans le contrôle de révision de l'histoire. Voici un outil qui n'a que pour darcs: http://tahoe-lafs.org/trac/darcsver/browser/trunk/README.rst et voici un extrait de code qui fait la même chose pour git: http://github.com/warner/python-ecdsa/blob/0ed702a9d4057ecf33eea969b8cf280eaccd89a1/setup.py#L34Cela devrait aussi fonctionner, en utilisant des expressions régulières et selon les champs de métadonnées de disposer d'un format comme ceci:
Utiliser le suivant au début de votre setup.py:
Après cela, vous pouvez utiliser les métadonnées dans votre script comme ceci:
Avec une structure comme ceci:
où version.py contient:
Vous pouvez le faire dans setup.py:
Cela ne cause pas de problème avec toutes les dépendances que vous avez dans votre mymodule/__init__.py
Pour éviter l'importation d'un fichier (et donc de l'exécution de son code), on peut l'analyser et récupérer les
version
attribut de l'arbre de syntaxe:Ce code tente de trouver le
__version__
ouVERSION
affectation au plus haut niveau du module de retour est une chaîne de valeur. Le côté droit peut être une chaîne ou un tuple.Il y a mille et une façons de la peau d'un chat -- voici la mienne:
Nettoyage https://stackoverflow.com/a/12413800 de @gringo-suave:
Nous avons voulu mettre les méta-informations sur nos offres
pypackagery
dans__init__.py
, mais ne pouvait pas car il a de la troisième partie des dépendances que PJ Eby l'a déjà souligné (voir sa réponse et l'avertissement concernant la condition de la course).Nous l'avons résolu en créant un module séparé
pypackagery_meta.py
qui contient seulement les méta-informations:ensuite importé le méta-informations dans
packagery/__init__.py
:et enfin utilisé dans
setup.py
:Vous devez inclure
pypackagery_meta
dans votre forfait avecpy_modules
installation argument. Sinon, vous ne pouvez pas importer lors de l'installation depuis le package de distribution en manque.Maintenant, c'est brut et les besoins de certains de raffinage (il peut même être un découvert membre d'appel dans pkg_resources que je l'ai raté), mais simplement, je ne vois pas pourquoi cela ne fonctionne pas, ni pourquoi personne n'a proposé de date (Googler autour de a pas tourné ce jusqu')...à noter que c'est Python 2.x, et aurait besoin d'exiger pkg_resources (soupir):
Simple et droite, créez un fichier appelé
source/package_name/version.py
avec le contenu suivant:Ensuite, sur votre fichier
source/package_name/__init__.py
, de l'importation de la version pour d'autres personnes à utiliser:Maintenant, vous pouvez le mettre sur les
setup.py
Testé avec Python
2.7
,3.3
,3.4
,3.5
,3.6
et3.7
sur Linux, Windows et Mac OS. Je l'ai utilisé sur mon paquet de l'Intégration et des Tests Unitaires pour tous ces plates-formes. Vous pouvez voir les résultats de.travis.yml
etappveyor.yml
ici:Une autre version est à l'aide de gestionnaire de contexte:
Vous pouvez également utiliser l'
codecs
module pour gérer l'unicode des erreurs à la fois sur le langage Python2.7
et3.6
Si vous écrivez un module Python 100% en C/C++ à l'aide de Python, C Extensions, vous pouvez faire la même chose, mais à l'aide de C/C++ au lieu de Python.
Sur ce cas, créez le
setup.py
:Qui lit la version du fichier
version.h
:Mais, ne pas oublier de créer le
MANIFEST.in
pour inclure leversion.h
fichier:Et il est intégré dans l'application principale avec:
Références: