395 votes

De manière Standard pour intégrer la version en python package?

Est-il un moyen standard pour associer chaîne de version avec un paquet python dans une telle manière que je pourrais faire la suite?

import foo
print foo.version

J'imagine que il y a une certaine façon de récupérer des données sans aucun supplément de coder en dur, depuis le mineur/majeur cordes sont spécifiés en setup.py déjà. Autre solution que j'ai trouvé était de disposer d' import __version__ mon foo/__init__.py puis ont __version__.py généré par setup.py.

201voto

oefe Points 9122

Pas directement la réponse à votre question, mais vous devriez envisager de nommer __version__, pas version.

C'est presque un quasi-standard. De nombreux modules de la bibliothèque standard, utilisez __version__, et il est également utilisé dans beaucoup de la 3e partie des modules, c'est donc la quasi-standard.

Généralement, __version__ est une chaîne, mais parfois, c'est aussi un float ou un tuple.

Edit: comme mentionné par S. Lott (Merci!), PEP 8 il est dit explicitement:

La Version De Tenue De Livres

Si vous disposez de la Subversion, CVS, ou RCS crud dans votre fichier source, faire comme suit.

    __version__ = "$Revision: 63990 $"
    # $Source$

Ces lignes doivent être inclus après le module de docstring, avant de tout autre code, séparés par une ligne vide au-dessus et au-dessous.

Vous devez également vous assurer que le numéro de version est conforme au format décrit dans la PPE 386 (PEP 440 est un projet destiné à remplacer la PPE 386 finalement).

170voto

Zooko Points 742

Voici comment je le fais. Avantages de la méthode suivante:

  1. Il fournit un __version__ d'attribut.

  2. Il fournit la norme de métadonnées version. Par conséquent, il sera détecté par pkg_resources ou d'autres outils qui analysent le paquet de métadonnées (EGG-INFO et/ou PKG-INFO, PEP 0345).

  3. Il n'a pas d'importation de votre colis (ou autre chose) lors de la construction de votre colis, ce qui peut causer des problèmes dans certaines situations. (Voir les commentaires ci-dessous sur ce que les problèmes que cela peut entraîner.)

  4. Il n'y a qu'un seul endroit que le numéro de version est écrite, donc il n'y a qu'un seul endroit à en changer lorsque le numéro de version change, et il ya moins de chance de versions incompatibles.

Voici comment cela fonctionne: le "canonique" pour enregistrer le numéro de version est un .py fichier, nommé "_version.py" ce qui est dans votre paquet Python, par exemple, en myniftyapp/_version.py. Ce fichier est un module Python, mais votre setup.py ne pas l'importer! (Qui irait à l'encontre de fonction 3.) Au lieu de votre setup.py sait que le contenu de ce fichier est très simple, quelque chose comme:

__version__ = "3.6.5"

Et si votre setup.py ouvre le fichier et l'analyse, avec un code comme:

import re
VERSIONFILE="myniftyapp/_version.py"
verstrline = open(VERSIONFILE, "rt").read()
VSRE = r"^__version__ = ['\"]([^'\"]*)['\"]"
mo = re.search(VSRE, verstrline, re.M)
if mo:
    verstr = mo.group(1)
else:
    raise RuntimeError("Unable to find version string in %s." % (VERSIONFILE,))

Alors votre setup.py passe d'une chaîne de caractères comme la valeur de la "version" argument setup(), satisfaisant ainsi de caractéristique 2.

Pour satisfaire caractéristique 1, vous pouvez avoir votre colis (au moment de l'exécution, et non pas au moment de l'installation!) importer le _version fichier à partir d' myniftyapp/__init__.py comme ceci:

from _version import __version__

Voici un exemple de cette technique que j'ai utilisé pendant des années.

Le code de cet exemple est un peu plus compliqué, mais l'exemple simplifié que j'ai écrit dans ce commentaire doit être une mise en œuvre complète.

Voici un exemple de code de l'importation de la version.

Si vous voyez quelque chose de mal avec cette approche, s'il vous plaît laissez-moi savoir: zooko à zooko dot com. Si vous ne voyez pas quelque chose de mal avec cette approche ensuite de l'utiliser! Parce que plus les paquets sont livrés avec leurs numéros de version dans les endroits les mieux!

141voto

sorin Points 23747

Ici est la meilleure solution que j'ai vu jusqu'à présent et il explique pourquoi:

À l'intérieur d' yourpackage/version.py:

# Store the version here so:
# 1) we don't load dependencies by storing it in __init__.py
# 2) we can import it in setup.py for the same reason
# 3) we can import it into your module module
__version__ = '0.12'

À l'intérieur d' yourpackage/__init__.py:

from .version import __version__

À l'intérieur d' setup.py:

exec(open('yourpackage/version.py').read())
setup(
    ...
    version=__version__,
    ...

Si vous connaissez une autre approche qui semble être mieux faites le moi savoir.

33voto

Oddthinking Points 8946

Un grand nombre de réponses affirment que "Il ne semble pas être un moyen standard" ou qu'un style "est presque un quasi-standard".

En fait, il est un moyen standard pour ce faire*:

Il décrit, avec justification, un (certes en option) standard pour les modules à suivre. Voici un extrait:

3) Lorsqu'un module (ou package) comprend un numéro de version, la version DEVRAIT être disponible dans l' __version__ d'attribut.

4) Pour les modules qui vivent à l'intérieur d'un espace de noms de package, le module DOIT inclure l' __version__ d'attribut. L'espace de noms de package lui-même ne DEVRAIT PAS inclure sa propre __version__ d'attribut.

5) L' __version__ la valeur de l'attribut DOIT être une chaîne.

* Édité à ajouter: Que par les commentaires, en fait, ce n'est pas une norme acceptée; elle a été reportée.

31voto

JAB Points 11053

Mais c'est sans doute trop tard, il est un peu plus simple alternative à la réponse précédente:

__version_info__ = ('1', '2', '3')
__version__ = '.'.join(__version_info__)

(Et il serait assez simple de convertir l'auto-incrémentation des portions de numéros de version d'une chaîne à l'aide de str().)

Bien sûr, de ce que j'ai vu, les gens ont tendance à utiliser quelque chose comme précédemment mentionné version lors de l'utilisation d' __version_info__, et en tant que tel magasin comme un n-uplet d'entiers; cependant, je n'arrive pas à voir le point de le faire, car je doute qu'il y a des situations où vous devez effectuer des opérations mathématiques, telles que l'addition et de la soustraction sur des portions de numéros de version pour n'importe quel but, outre la curiosité ou de l'auto-incrémentation (et même alors, int() et str() peut être utilisé assez facilement). (D'un autre côté, il y a la possibilité de quelqu'un d'autre code attend numérique tuple plutôt qu'une chaîne n-uplet et donc défaut.)

C'est, bien sûr, de mon propre point de vue, et je serais heureux de faire comme les autres' entrée sur le numérique à l'aide d'un tuple.


Comme shezi m'a rappelé, (lexicale) les comparaisons de chaînes de nombre n'ont pas forcément le même résultat que le numérique directe des comparaisons; les zéros à gauche serait amené à fournir. Donc en fin de compte, le stockage __version_info__ (ou de ce qu'il serait appelé) comme un n-uplet de valeurs entières permettrait une plus grande efficacité de comparaisons entre les versions.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X