Si j'ai un script Python qui nécessite au moins une version particulière de Python, quelle est la bonne façon d'échouer correctement lorsqu'une version antérieure de Python est utilisée pour lancer le script?
Comment obtenir le contrôle suffisamment tôt pour émettre un message d'erreur et quitter?
Par exemple, j'ai un programme qui utilise l'opérateur de ternerie (nouveau en 2.5) et des blocs "avec" (nouveau en 2.6). J'ai écrit une petite routine simple de vérificateur de version d'interpréteur qui est la première chose que le script appellerait ... sauf qu'il ne va pas aussi loin. Au lieu de cela, le script échoue pendant la compilation de python, avant même que mes routines soient appelées. Ainsi, l'utilisateur du script voit des traces d'erreurs de synchronisation très obscures - qui nécessitent à peu près un expert pour déduire qu'il s'agit simplement d'exécuter la mauvaise version de Python.
Je sais comment vérifier la version de Python. Le problème est qu'une syntaxe est illégale dans les anciennes versions de Python. Considérez ce programme:
import sys
if sys.version_info < (2, 4):
raise "must use python 2.5 or greater"
else:
# syntax error in 2.4, ok in 2.5
x = 1 if True else 2
print x
Lorsque exécuté sous 2.4, je veux ce résultat
$ ~/bin/python2.4 tern.py
must use python 2.5 or greater
et non ce résultat:
$ ~/bin/python2.4 tern.py
File "tern.py", line 5
x = 1 if True else 2
^
SyntaxError: invalid syntax
(Canalisation pour un collègue.)
Réponses:
Vous pouvez tester en utilisant
eval
:Aussi,
with
est disponible en Python 2.5, il suffit d'ajouterfrom __future__ import with_statement
.EDIT: pour obtenir le contrôle suffisamment tôt, vous pouvez le diviser en différents
.py
fichiers et vérifier la compatibilité dans le fichier principal avant l'importation (par exemple__init__.py
dans un package):la source
exec
place deeval
. J'ai eu ce problème en essayant d'écrire une fonction qui s'imprimerait sur stderr dans py2k et py3k.import
station dans try / except). Notez que vous devrez peut-être vérifier autre chose queSyntaxError
par exemple (par exemple, les fonctions intégrées ou les ajouts à la bibliothèque standard)Ayez un wrapper autour de votre programme qui fait ce qui suit.
Vous pouvez également envisager d'utiliser
sys.version()
, si vous prévoyez de rencontrer des personnes qui utilisent des interprètes Python antérieurs à 2.0, mais vous avez alors quelques expressions régulières à faire.Et il pourrait y avoir des façons plus élégantes de le faire.
la source
sys.version_info
n'est pas une fonction.import this
. Une belle diversion.Essayer
Devrait vous donner une chaîne comme "2.3.1". Si ce n'est pas exactement ce que vous voulez, il existe un riche ensemble de données disponibles via le build-in "plateforme". Ce que vous voulez devrait être quelque part.
la source
print(platform.python_version())
au lieu deplatform.python_version()
!La meilleure façon de faire cette comparaison de versions est probablement d'utiliser le
sys.hexversion
. Ceci est important car la comparaison des tuples de version ne vous donnera pas le résultat souhaité dans toutes les versions de python.la source
la source
sys.version_info
n'est pas un tuple nommé. Vous devrez utilisersys.version_info[0]
pour le numéro de version majeur etsys.version_info[1]
pour le mineur.Vous pouvez également vérifier la version Python à partir du code lui-même en utilisant le
platform
module de la bibliothèque standard.Il y a deux fonctions:
platform.python_version()
(renvoie une chaîne).platform.python_version_tuple()
(retourne un tuple).Le code Python
Méthode simple pour vérifier la version:
Vous pouvez également utiliser la
eval
méthode:Exécutez le fichier Python dans une ligne de commande:
La sortie de Python avec CGI via un serveur WAMP sous Windows 10:
Ressources utiles
la source
Les ensembles sont devenus une partie du langage de base de Python 2.4, afin de rester rétrocompatible. Je l'ai fait à l'époque, ce qui fonctionnera également pour vous:
la source
try: set except NameError: from sets import Set as set
Bien que la question soit: comment obtenir le contrôle suffisamment tôt pour émettre un message d'erreur et quitter ?
La question à laquelle je réponds est: comment obtenir le contrôle suffisamment tôt pour émettre un message d'erreur avant de démarrer l'application ?
Je peux y répondre très différemment des autres articles. Il semble que les réponses tentent jusqu'à présent de résoudre votre question depuis Python.
Je dis, faites une vérification de version avant de lancer Python. Je vois que votre chemin est Linux ou unix. Cependant je ne peux que vous proposer un script Windows. Je pense que l'adapter à la syntaxe de script Linux ne serait pas trop difficile.
Voici le script DOS avec la version 2.7:
Cela n'exécute aucune partie de votre application et ne déclenchera donc pas d'exception Python. Il ne crée aucun fichier temporaire et n'ajoute aucune variable d'environnement OS. Et cela ne met pas votre application à une exception en raison de règles de syntaxe de version différentes. C'est trois points d'accès de sécurité moins possibles.
La
FOR /F
ligne est la clé.Pour plusieurs versions de python, consultez l'url: http://www.fpschultze.de/modules/smartfaq/faq.php?faqid=17
Et ma version hack:
[Script MS; Vérification de la version Python avant le lancement du module Python] http://pastebin.com/aAuJ91FQ
la source
obtiendra une réponse comme celle-ci
ici 2.7.6 est la version
la source
Comme indiqué ci-dessus, des erreurs de syntaxe se produisent au moment de la compilation et non au moment de l'exécution. Alors que Python est un "langage interprété", le code Python n'est pas réellement directement interprété; il est compilé en code octet, qui est ensuite interprété. Il y a une étape de compilation qui se produit lorsqu'un module est importé (s'il n'y a pas de version déjà compilée disponible sous la forme d'un fichier .pyc ou .pyd) et c'est là que vous obtenez votre erreur, pas (tout à fait exactement) quand votre code est en cours d'exécution.
Vous pouvez différer l'étape de compilation et la faire se produire au moment de l'exécution pour une seule ligne de code, si vous le souhaitez, en utilisant eval, comme indiqué ci-dessus, mais je préfère personnellement éviter de le faire, car cela fait que Python fonctionne potentiellement compilation inutile au moment de l'exécution, pour une chose et pour une autre, cela crée ce qui me semble être un encombrement de code. (Si vous le souhaitez, vous pouvez générer du code qui génère du code qui génère du code - et avoir un temps absolument fabuleux à modifier et à déboguer dans 6 mois.) Donc, je recommanderais plutôt quelque chose comme ceci:
.. ce que je ferais même si je n'avais qu'une seule fonction qui utilisait une syntaxe plus récente et c'était très court. (En fait, je prendrais toutes les mesures raisonnables pour minimiser le nombre et la taille de ces fonctions. Je pourrais même écrire une fonction comme ifTrueAElseB (cond, a, b) avec cette seule ligne de syntaxe.)
Une autre chose qui mérite d'être soulignée (que je suis un peu étonné que personne n'ait encore souligné) est que, même si les versions antérieures de Python ne prenaient pas en charge le code comme
..il a pris en charge le code comme
C'était l'ancienne façon d'écrire des expressions ternaires. Je n'ai pas encore installé Python 3, mais pour autant que je sache, cette "ancienne" méthode fonctionne toujours à ce jour, vous pouvez donc décider vous-même si cela vaut la peine d'utiliser conditionnellement la nouvelle syntaxe, si vous avez besoin pour prendre en charge l'utilisation des anciennes versions de Python.
la source
a and b or c
place deb if a else c
, ce n'est pas équivalent; si elleb
est fausse, elle échouera, produisanta
plutôt queb
.Mettez ce qui suit tout en haut de votre fichier:
Continuez ensuite avec le code Python normal:
la source
sys.version_info < (2, 7)
sys.version_info
type à un tuple fonctionne?sys.version_info
était un tuple; par exemple(2, 4, 6, 'final', 0)
; ce n'est qu'en Python 3 et 2.7 qu'il a été changé en un type distinct, qui est néanmoins comparable aux tuples.Je pense que la meilleure façon est de tester les fonctionnalités plutôt que les versions. Dans certains cas, c'est trivial, pas dans d'autres.
par exemple:
Tant que vous êtes suffisamment précis pour utiliser les blocs try / except, vous pouvez couvrir la plupart de vos bases.
la source
Je viens de trouver cette question après une recherche rapide tout en essayant de résoudre le problème moi-même et j'ai trouvé un hybride basé sur quelques-unes des suggestions ci-dessus.
J'aime l'idée de DevPlayer d'utiliser un script d'encapsuleur, mais l'inconvénient est que vous finissez par maintenir plusieurs encapsuleurs pour différents systèmes d'exploitation, j'ai donc décidé d'écrire l'encapsuleur en python, mais utilisez la même logique de base "saisir la version en exécutant l'exe". et est venu avec cela.
Je pense que cela devrait fonctionner pour 2.5 et au-delà. Je l'ai testé sur 2.66, 2.7.0 et 3.1.2 sur Linux et 2.6.1 sur OS X jusqu'à présent.
Oui, je sais que la ligne finale de décodage / strip est horrible, mais je voulais juste saisir rapidement le numéro de version. Je vais affiner cela.
Cela fonctionne assez bien pour moi pour l'instant, mais si quelqu'un peut l'améliorer (ou me dire pourquoi c'est une terrible idée), ce serait cool aussi.
la source
Pour les scripts python autonomes , l'astuce docstring de module suivante pour appliquer une version python (ici v2.7.x) fonctionne (testée sur * nix).
Cela devrait également gérer l'exécutable python manquant mais a une dépendance sur grep. Voir ici pour le contexte.
la source
Vous pouvez vérifier avec
sys.hexversion
ousys.version_info
.sys.hexversion
n'est pas très convivial pour les humains car c'est un nombre hexadécimal.sys.version_info
est un tuple, il est donc plus convivial pour l'homme.Vérifiez Python 3.6 ou plus récent avec
sys.hexversion
:Vérifiez Python 3.6 ou plus récent avec
sys.version_info
:sys.version_info
est plus convivial pour l'homme, mais prend plus de personnages. Je recommanderaissys.hexversion
, même si c'est moins convivial pour l'homme.J'espère que cela vous a aidé!
la source
Je développe l'excellente réponse d'Akhan, qui affiche un message utile avant même que le script Python ne soit compilé.
Si vous voulez vous assurer que le script est exécuté avec Python 3.6 ou plus récent, ajoutez ces deux lignes en haut de votre script Python:
(Remarque: la deuxième ligne commence par quatre guillemets simples et se termine par trois guillemets simples. Cela peut sembler étrange, mais ce n'est pas une faute de frappe.)
L'avantage de cette solution est que le code comme
print(f'Hello, {name}!')
ne causera pas deSyntaxError
si une version Python plus ancienne que 3.6 est utilisée. Vous verrez plutôt ce message utile:Bien sûr, cette solution ne fonctionne que sur des shells de type Unix, et uniquement lorsque le script est appelé directement (tel que
./script.py
:), et avec les bons bits d'autorisation eXecute définis.la source
Que dis-tu de ça:
la source
Le problème est assez simple. Vous avez vérifié si la version était inférieure à 2,4, pas inférieure ou égale à . Donc, si la version Python est 2.4, elle n'est pas inférieure à 2.4. Vous auriez dû avoir:
, ne pas
la source