Wenn ich ein Python-Skript habe, für das mindestens eine bestimmte Version von Python erforderlich ist, wie kann ich dann ordnungsgemäß fehlschlagen, wenn eine frühere Version von Python zum Starten des Skripts verwendet wird?
Wie erhalte ich früh genug die Kontrolle, um eine Fehlermeldung auszugeben und zu beenden?
Zum Beispiel habe ich ein Programm, das den ternery-Operator (neu in 2.5) und "with" -Blöcke (neu in 2.6) verwendet. Ich habe eine einfache kleine Routine zur Überprüfung der Interpreterversion geschrieben, die das erste ist, was das Skript aufrufen würde ... außer es kommt nicht so weit. Stattdessen schlägt das Skript während der Python-Kompilierung fehl, bevor meine Routinen überhaupt aufgerufen werden. Daher sieht der Benutzer des Skripts einige sehr undurchsichtige Rückverfolgungen von Synaxfehlern, bei denen ein Experte feststellen muss, dass einfach die falsche Version von Python ausgeführt wird.
Ich weiß, wie man die Version von Python überprüft. Das Problem ist, dass einige Syntax in älteren Versionen von Python illegal ist. Betrachten Sie dieses Programm:
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
Wenn ich unter 2.4 laufe, möchte ich dieses Ergebnis
$ ~/bin/python2.4 tern.py
must use python 2.5 or greater
und nicht dieses Ergebnis:
$ ~/bin/python2.4 tern.py
File "tern.py", line 5
x = 1 if True else 2
^
SyntaxError: invalid syntax
(Channeling für einen Mitarbeiter.)
Antworten:
Sie können testen mit
eval
:Auch
with
ist in Python verfügbar 2.5, fügen Sie einfachfrom __future__ import with_statement
.BEARBEITEN: Um die Kontrolle früh genug zu erhalten, können Sie sie
.py
vor dem Import in verschiedene Dateien aufteilen und die Kompatibilität in der Hauptdatei überprüfen (z. B.__init__.py
in einem Paket):quelle
exec
stattdessen verwenden müsseneval
. Ich hatte dies beim Versuch, eine Funktion zu schreiben, die sowohl in py2k als auch in py3k auf stderr gedruckt wird.import
Station in try / Except). Beachten Sie, dass Sie möglicherweise auch nach anderen DingenSyntaxError
suchen müssen (z. B. nach integrierten Funktionen oder Ergänzungen zur Standardbibliothek)Haben Sie einen Wrapper um Ihr Programm, der Folgendes ausführt.
Sie können auch die Verwendung in Betracht ziehen
sys.version()
, wenn Sie vorhaben, Personen zu begegnen, die Python-Interpreter vor 2.0 verwenden, aber dann einige reguläre Ausdrücke zu erledigen haben.Und es könnte elegantere Möglichkeiten geben, dies zu tun.
quelle
sys.version_info
ist keine Funktion.import this
. Eine schöne Abwechslung.Versuchen
Sollte Ihnen eine Zeichenfolge wie "2.3.1" geben. Wenn dies nicht genau das ist, was Sie möchten, steht über das integrierte "Plattform" eine Vielzahl von Daten zur Verfügung. Was Sie wollen, sollte irgendwo drin sein.
quelle
print(platform.python_version())
stattplatform.python_version()
!Der wahrscheinlich beste Weg, um diesen Versionsvergleich durchzuführen, ist die Verwendung von
sys.hexversion
. Dies ist wichtig, da beim Vergleichen von Versionstupeln nicht in allen Python-Versionen das gewünschte Ergebnis erzielt wird.quelle
quelle
sys.version_info
ist nicht ein benannter Tupel. Sie müssensys.version_info[0]
für die Hauptversionsnummer undsys.version_info[1]
für die Nebenversion verwenden.Sie können die Python-Version auch mithilfe des
platform
Moduls aus der Standardbibliothek anhand des Codes selbst überprüfen .Es gibt zwei Funktionen:
platform.python_version()
(gibt einen String zurück).platform.python_version_tuple()
(gibt Tupel zurück).Der Python-Code
Einfache Methode zum Überprüfen der Version:
Sie können auch die folgende
eval
Methode verwenden:Führen Sie die Python-Datei in einer Befehlszeile aus:
Die Ausgabe von Python mit CGI über einen WAMP-Server unter Windows 10:
Hilfreiche Ressourcen
quelle
Sets wurden Teil der Kernsprache in Python 2.4, um abwärtskompatibel zu bleiben. Ich habe das damals gemacht, was auch für Sie funktionieren wird:
quelle
try: set except NameError: from sets import Set as set
Obwohl die Frage lautet: Wie erhalte ich die Kontrolle früh genug, um eine Fehlermeldung auszugeben und zu beenden ?
Die Frage, die ich beantworte, lautet: Wie erhalte ich früh genug die Kontrolle, um vor dem Starten der App eine Fehlermeldung auszugeben ?
Ich kann es ganz anders beantworten als die anderen Beiträge. Bisher scheinen die Antworten zu versuchen, Ihre Frage aus Python heraus zu lösen.
Ich sage, machen Sie eine Versionsprüfung, bevor Sie Python starten. Ich sehe, dein Weg ist Linux oder Unix. Ich kann Ihnen jedoch nur ein Windows-Skript anbieten. Ich würde mir vorstellen, dass die Anpassung an die Linux-Skriptsyntax nicht allzu schwierig wäre.
Hier ist das DOS-Skript mit Version 2.7:
Dies führt keinen Teil Ihrer Anwendung aus und löst daher keine Python-Ausnahme aus. Es werden keine temporären Dateien erstellt oder Betriebssystemumgebungsvariablen hinzugefügt. Und Ihre App wird aufgrund unterschiedlicher Versionssyntaxregeln nicht zu einer Ausnahme. Das sind drei weniger mögliche Sicherheitspunkte für den Zugriff.
Die
FOR /F
Linie ist der Schlüssel.Informationen zur Version mit mehreren Pythons finden Sie unter der URL: http://www.fpschultze.de/modules/smartfaq/faq.php?faqid=17
Und meine Hack-Version:
[MS-Skript; Überprüfung der Python-Version vor dem Start des Python-Moduls] http://pastebin.com/aAuJ91FQ
quelle
wird eine Antwort wie diese bekommen
hier ist 2.7.6 Version
quelle
Wie oben erwähnt, treten Syntaxfehler zur Kompilierungszeit und nicht zur Laufzeit auf. Während Python eine "interpretierte Sprache" ist, wird Python-Code nicht direkt interpretiert. Es wird zu Bytecode kompiliert, der dann interpretiert wird. Es gibt einen Kompilierungsschritt, der ausgeführt wird, wenn ein Modul importiert wird (wenn keine bereits kompilierte Version in Form einer .pyc- oder .pyd-Datei verfügbar ist), und dann erhalten Sie Ihren Fehler, nicht (ganz genau) wann Ihr Code wird ausgeführt.
Sie können den Kompilierungsschritt verschieben und ihn zur Laufzeit für eine einzelne Codezeile ausführen, wenn Sie möchten, indem Sie wie oben erwähnt eval verwenden. Ich persönlich ziehe es jedoch vor, dies zu vermeiden, da Python dadurch möglicherweise eine Leistung erbringt Eine unnötige Laufzeitkompilierung zum einen und zum anderen schafft das, was sich für mich wie Code-Unordnung anfühlt. (Wenn Sie möchten, können Sie Code generieren, der Code generiert, der Code generiert - und in 6 Monaten eine fabelhafte Zeit damit haben, diesen zu ändern und zu debuggen.) Ich würde also stattdessen etwas Ähnliches empfehlen:
.. was ich tun würde, selbst wenn ich nur eine Funktion hätte, die eine neuere Syntax verwendet und sehr kurz ist. (Tatsächlich würde ich alle vernünftigen Maßnahmen ergreifen, um die Anzahl und Größe solcher Funktionen zu minimieren. Ich könnte sogar eine Funktion wie ifTrueAElseB (cond, a, b) mit dieser einzelnen Syntaxzeile schreiben.)
Eine andere Sache, die es wert sein könnte, darauf hingewiesen zu werden (dass ich ein wenig erstaunt bin, dass noch niemand darauf hingewiesen hat), ist, dass frühere Versionen von Python Code wie diesen nicht unterstützten
..es hat Code wie unterstützt
Das war die alte Art, ternäre Ausdrücke zu schreiben. Ich habe Python 3 noch nicht installiert, aber soweit ich weiß, funktioniert dieser "alte" Weg bis heute, sodass Sie selbst entscheiden können, ob es sich lohnt, die neue Syntax bei Bedarf unter bestimmten Bedingungen zu verwenden um die Verwendung älterer Versionen von Python zu unterstützen.
quelle
a and b or c
stattdessenb if a else c
ist es nicht gleichwertig; Wennb
es falsch ist, wird es scheitern unda
eher produzieren alsb
.Fügen Sie Folgendes ganz oben in Ihre Datei ein:
Fahren Sie dann mit dem normalen Python-Code fort:
quelle
sys.version_info < (2, 7)
sys.version_info
Typs mit einem Tupel funktioniert?sys.version_info
früher ein Tupel; zum Beispiel(2, 4, 6, 'final', 0)
; nur in Python 3 und 2.7 wurde es in einen separaten Typ geändert, der dennoch mit Tupeln vergleichbar ist.Ich denke, der beste Weg ist, eher auf Funktionalität als auf Versionen zu testen. In einigen Fällen ist dies trivial, in anderen nicht.
z.B:
Solange Sie in der Verwendung der Try / Except-Blöcke genau genug sind, können Sie die meisten Ihrer Basen abdecken.
quelle
Ich habe diese Frage erst nach einer kurzen Suche gefunden, als ich versucht habe, das Problem selbst zu lösen, und ich habe einen Hybrid entwickelt, der auf einigen der obigen Vorschläge basiert.
Ich mag die Idee von DevPlayer, ein Wrapper-Skript zu verwenden, aber der Nachteil ist, dass Sie am Ende mehrere Wrapper für verschiedene Betriebssysteme verwalten. Deshalb habe ich beschlossen, den Wrapper in Python zu schreiben, aber dieselbe grundlegende "Grab the version by run the exe" -Logik zu verwenden und kam mit diesem.
Ich denke, es sollte ab 2.5 funktionieren. Ich habe es bisher auf 2.66, 2.7.0 und 3.1.2 unter Linux und 2.6.1 unter OS X getestet.
Ja, ich weiß, dass die endgültige Dekodierungs- / Streifenzeile schrecklich ist, aber ich wollte nur schnell die Versionsnummer abrufen. Ich werde das verfeinern.
Das funktioniert für mich im Moment gut genug, aber wenn jemand es verbessern kann (oder mir sagen kann, warum es eine schreckliche Idee ist), wäre das auch cool.
quelle
Bei eigenständigen Python-Skripten funktioniert der folgende Modul-Docstring-Trick zum Erzwingen einer Python-Version (hier v2.7.x) (getestet unter * nix).
Dies sollte auch die fehlende ausführbare Python-Datei behandeln, ist jedoch von grep abhängig. Hintergrundinformationen finden Sie hier .
quelle
Sie können mit
sys.hexversion
oder überprüfensys.version_info
.sys.hexversion
ist nicht sehr menschenfreundlich, weil es eine Hexadezimalzahl ist.sys.version_info
ist ein Tupel, also menschlicher.Suchen Sie nach Python 3.6 oder neuer mit
sys.hexversion
:Suchen Sie nach Python 3.6 oder neuer mit
sys.version_info
:sys.version_info
ist menschenfreundlicher, nimmt aber mehr Charaktere auf. Ich würde empfehlensys.hexversion
, obwohl es weniger menschenfreundlich ist.Ich hoffe das hat dir geholfen!
quelle
Ich erweitere Akhans ausgezeichnete Antwort, die eine hilfreiche Nachricht druckt, bevor das Python-Skript überhaupt kompiliert wird.
Wenn Sie sicherstellen möchten, dass das Skript mit Python 3.6 oder höher ausgeführt wird, fügen Sie diese beiden Zeilen oben in Ihr Python-Skript ein:
(Hinweis: Die zweite Zeile beginnt mit vier einfachen Anführungszeichen und endet mit drei einfachen Anführungszeichen. Dies mag seltsam aussehen, ist aber kein Tippfehler.)
Der Vorteil dieser Lösung ist, dass Code wie
print(f'Hello, {name}!')
kein verursacht,SyntaxError
wenn eine Python-Version älter als 3.6 verwendet wird. Stattdessen wird diese hilfreiche Nachricht angezeigt:Natürlich funktioniert diese Lösung nur bei Unix-ähnlichen Shells und nur, wenn das Skript direkt aufgerufen wird (z. B.
./script.py
:) und die richtigen eXecute-Berechtigungsbits gesetzt sind.quelle
Wie wäre es damit:
quelle
Das Problem ist ganz einfach. Sie haben überprüft, ob die Version kleiner als 2.4, nicht kleiner oder gleich . Wenn die Python-Version 2.4 ist, ist sie nicht kleiner als 2.4. Was Sie hätten haben sollen, war:
nicht
quelle