it-swarm.com.de

Wie kann ich in einem Programm, das neue Sprachfunktionen verwendet, nach der Python-Version suchen?

Wenn ich ein Python-Skript habe, das mindestens eine bestimmte -Version von Python erfordert, was ist der richtige Weg, um fehlerfrei auszufallen __, wenn eine frühere Version von Python zum Starten des Skripts verwendet wird?

Wie erhalte ich die Kontrolle früh genug, 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 schrieb eine einfache, kleine Interpreter-Version Checker-Routine, die das Skript als erstes tun würdecall ... außer, dass es nicht so weit kommt. Stattdessen schlägt das Skript .__ während der Python-Kompilierung fehl, noch bevor meine Routinen Aufgerufen werden. Der Benutzer des Skripts sieht also einige Obscure Synax-Fehler-Tracebacks - was ziemlich viel erfordert ein Experte, um daraus abzuleiten, dass es einfach darum geht, Die falsche Version von Python auszuführen.

Ich kann die Version von Python überprüfen. Das Problem ist, dass einige Syntax in älteren Python-Versionen ungültig 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.)

234
Mark Harrison

Sie können mit eval testen:

try:
  eval("1 if True else 2")
except SyntaxError:
  # doesn't have ternary

Außerdem ist with in Python 2.5 verfügbar. Fügen Sie einfach from __future__ import with_statement hinzu.

BEARBEITEN: Um die Kontrolle früh genug zu erlangen, können Sie sie vor dem Import in verschiedene .py-Dateien aufteilen und die Kompatibilität in der Hauptdatei überprüfen (z. B. in __init__.py in einem Paket):

# __init__.py

# Check compatibility
try:
  eval("1 if True else 2")
except SyntaxError:
  raise ImportError("requires ternary support")

# import from another module
from impl import *
106
orip

Habe einen Wrapper für dein Programm, der Folgendes tut.

import sys

req_version = (2,5)
cur_version = sys.version_info

if cur_version >= req_version:
   import myApp
   myApp.run()
else:
   print "Your Python interpreter is too old. Please consider upgrading."

Sie können sys.version() auch in Betracht ziehen, wenn Sie Personen begegnen möchten, die Python-Interpreter vor Version 2.0 verwenden. Sie müssen jedoch einige reguläre Ausdrücke verwenden.

Und es könnte elegantere Wege geben, dies zu tun.

102
Ed Carrel

Versuchen 

 Importplattform 
 Plattform.python_version () 

Sollte Ihnen eine Zeichenfolge wie "2.3.1" geben. Wenn dies nicht genau das ist, was Sie möchten, gibt es eine Vielzahl von Daten, die über das "Plattform" -Bau-In zur Verfügung stehen. Was Sie wollen, sollte irgendwo drin sein. 

30
James Anderson

Der beste Weg, diesen Versionsvergleich durchzuführen, ist die Verwendung von sys.hexversion. Dies ist wichtig, da beim Vergleich von Versionstupeln nicht in allen Python-Versionen das gewünschte Ergebnis erzielt wird.

import sys
if sys.hexversion < 0x02060000:
    print "yep!"
else:
    print "oops!"
22
sorin
import sys    
# prints whether python is version 3 or not
python_version = sys.version_info.major
if python_version == 3:
    print("is python 3")
else:
    print("not python 3")
15
Erick Wendel

Antwort von Nykakin an AskUbuntu :

Sie können die Python-Version auch anhand des Codes selbst überprüfen, indem Sie das Modul platform aus der Standardbibliothek verwenden.

Es gibt zwei Funktionen:

  • platform.python_version() (gibt String zurück).
  • platform.python_version_Tuple() (gibt Tuple zurück).

Der Python-Code

Erstellen Sie eine Datei zum Beispiel: version.py)

Einfache Methode zur Überprüfung der Version:

import platform

print(platform.python_version())
print(platform.python_version_Tuple())

Sie können auch die eval-Methode verwenden:

try:
  eval("1 if True else 2")
except SyntaxError:
  raise ImportError("requires ternary support")

Führen Sie die Python-Datei in einer Befehlszeile aus:

$ python version.py 
2.7.11
('2', '7', '11')

Die Ausgabe von Python mit CGI über einen WAMP-Server unter Windows 10:

 Screenshot 2016-11-16 14.39.01 by Suriyaa Kudo


Hilfreiche Ressourcen

9
Suriyaa

Obwohl die Frage ist: Wie erhalte ich die Kontrolle früh genug, um eine Fehlernachricht auszugeben und zu beenden?

Die Frage, die ich beantworte, lautet: Wie erhalte ich die Kontrolle, um vor dem Starten der App eine Fehlermeldung auszugeben?

Ich kann es viel anders beantworten als die anderen Posts ... Die Antworten scheinen zu versuchen, Ihre Frage aus Python heraus zu lösen.

Ich sage, prüfe die Version, bevor du Python startest. Ich sehe, dass Ihr Pfad Linux oder Unix ist . Allerdings kann ich Ihnen nur ein Windows-Skript anbieten. Es wäre nicht zu schwer, das Image an Linux-Skriptsyntax anzupassen.

Hier ist das DOS-Skript mit Version 2.7:

@ECHO OFF
REM see http://ss64.com/nt/for_f.html
FOR /F "tokens=1,2" %%G IN ('"python.exe -V 2>&1"') DO ECHO %%H | find "2.7" > Nul
IF NOT ErrorLevel 1 GOTO Python27
ECHO must use python2.7 or greater
GOTO EOF
:Python27
python.exe tern.py
GOTO EOF
:EOF

Dies führt keinen Teil Ihrer Anwendung aus und verursacht daher keine Python-Ausnahme. Es erstellt keine temporäre Datei und fügt keine OS-Umgebungsvariablen hinzu. Und Ihre App endet nicht aufgrund von unterschiedlichen Versionssyntaxregeln zu einer Ausnahme. Das sind drei weniger mögliche Sicherheitszugriffspunkte.

Die FOR /F-Zeile ist der Schlüssel.

FOR /F "tokens=1,2" %%G IN ('"python.exe -V 2>&1"') DO ECHO %%H | find "2.7" > Nul

Für mehrere Python-Versionen überprüfen Sie die URL: http://www.fpschultze.de/modules/smartfaq/faq.php?faqid=17

Und meine Hack-Version:

[MS-Skript; Prüfung der Python-Version vor dem Python-Modul] http://Pastebin.com/aAuJ91FQ

7
DevPlayer

Sets wurden in Python 2.4 Teil der Kernsprache, um abwärtskompatibel zu bleiben. Ich habe das damals gemacht, was auch für Sie funktionieren wird:

if sys.version_info < (2, 4):
    from sets import Set as set
7
André
import sys
sys.version

wird so eine Antwort bekommen 

"2.7.6 (Standardeinstellung 26. Oktober 2016, 20:30:19)\n [GCC 4.8.4]"

hier 2.7.6 ist version

3

Wie bereits 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 Byte-Code kompiliert, der dann interpretiert wird. Es gibt einen Kompilierungsschritt, der auftritt, wenn ein Modul importiert wird (wenn keine bereits kompilierte Version in Form einer .pyc- oder .pyd-Datei verfügbar ist). In diesem Fall erhalten Sie Ihren Fehler, nicht (ganz genau), wann Ihr Code läuft. 

Sie können den Kompilierungsschritt verschieben und zur Laufzeit für eine einzelne Codezeile ausführen, wenn Sie möchten, indem Sie eval verwenden (siehe oben), aber ich persönlich bevorzuge es, dies zu tun, da Python möglicherweise dazu führt, dass dies ausgeführt wird unnötige Runtime-Kompilierung, zum einen und zum anderen, was für mich das Gefühl von Code-Unordnung erzeugt. (Wenn Sie möchten, können Sie Code generieren, der Code generiert, der Code generiert - und Sie haben eine absolut fantastische Zeit, um dies in sechs Monaten zu ändern und zu debuggen.) Was ich stattdessen empfehlen würde, ist Folgendes:

import sys
if sys.hexversion < 0x02060000:
    from my_module_2_5 import thisFunc, thatFunc, theOtherFunc
else:
    from my_module import thisFunc, thatFunc, theOtherFunc

... was ich auch tun würde, wenn ich nur eine Funktion hätte, die neuere Syntax verwendete und diese sehr kurz war. (Tatsächlich würde ich jede vernünftige Maßnahme 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, auf die es sich lohnt, darauf hinzuweisen (dass ich ein wenig erstaunt bin, auf die noch niemand hingewiesen hat) ist, dass frühere Versionen von Python Code nicht unterstützten

value = 'yes' if MyVarIsTrue else 'no'

..es hat Code wie unterstützt

value = MyVarIsTrue and 'yes' or 'no'

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 bedingt zu verwenden, wenn Sie es brauchen um die Verwendung älterer Python-Versionen zu unterstützen.

2
Shavais

Fügen Sie Folgendes ganz oben in Ihre Datei ein:

import sys

if float(sys.version.split()[0][:3]) < 2.7:
    print "Python 2.7 or higher required to run this code, " + sys.version.split()[0] + " detected, exiting."
    exit(1)

Fahren Sie dann mit dem normalen Python-Code fort:

import ...
import ...
other code...
2
jml

Ich denke, der beste Weg ist, eher die Funktionalität als die Versionen zu testen. In einigen Fällen ist dies trivial, in anderen nicht.

z.B:

try :
    # Do stuff
except : # Features weren't found.
    # Do stuff for older versions.

Solange Sie die Try/Except-Blöcke genau genug kennen, können Sie die meisten Ihrer Basen behandeln.

1
sykora

Für standalone - Python-Skripts funktioniert der folgende Modul-Docstring-Trick, um eine Python-Version (hier v2.7.x) zu erzwingen (getestet auf * nix).

#!/bin/sh
''''python -V 2>&1 | grep -q 2.7 && exec python -u -- "$0" ${1+"[email protected]"}; echo "python 2.7.x missing"; exit 1 # '''

import sys
[...]

Dies sollte auch die fehlende ausführbare Python-Datei behandeln, hängt jedoch von grep ab. hier zum Hintergrund.

1
akhan

Ich habe diese Frage nach einer kurzen Suche gefunden, als ich versuchte, das Problem selbst zu lösen, und ich habe einen Hybrid entwickelt, der auf einigen der oben genannten 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. Daher habe ich mich dazu entschieden, den Wrapper in Python zu schreiben, aber ich verwende die gleiche grundlegende Logik "greifen Sie die Version durch Ausführen der Exe-Logik" und kam dazu. 

Ich denke, es sollte ab 2.5 funktionieren. Ich habe es bisher unter 2.66, 2.7.0 und 3.1.2 unter Linux und 2.6.1 unter OS X getestet.

import sys, subprocess
args = [sys.executable,"--version"]

output, error = subprocess.Popen(args ,stdout = subprocess.PIPE, stderr = subprocess.PIPE).communicate()
print("The version is: '%s'"  %error.decode(sys.stdout.encoding).strip("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLMNBVCXZ,.+ \n") )

Ja, ich weiß, dass die endgültige Decodier-/Strip-Zeile schrecklich ist, aber ich wollte nur schnell die Versionsnummer einholen. Ich werde das verfeinern.

Das funktioniert für mich jetzt gut genug, aber wenn jemand es verbessern kann (oder mir sagen könnte, warum das eine schreckliche Idee ist), wäre das auch cool.

1
Steve

Ich erweitere die exzellente Antwort von akhan, die eine hilfreiche Nachricht ausgibt bevor das Python-Skript sogar kompiliert wird.

Wenn Sie sicherstellen möchten, dass das Skript mit Python 3.6 oder neuer ausgeführt wird, fügen Sie diese beiden Zeilen oben in Ihr Python-Skript ein:

#!/bin/sh
''''python3 -c 'import sys; sys.exit(sys.version_info < (3, 6))' && exec python3 -u -- "$0" ${1+"[email protected]"}; echo 'This script requires Python 3.6 or newer.'; exit 1 # '''

(Hinweis: Die zweite Zeile beginnt mit vier einfachen Anführungszeichen und endet mit drei einfachen Anführungszeichen. Dies kann merkwürdig aussehen, ist jedoch kein Tippfehler.)

Der Vorteil dieser Lösung besteht darin, dass Code wie print(f'Hello, {name}!') keine SyntaxError verursacht, wenn eine ältere Python-Version als 3.6 verwendet wird. Diese hilfreiche Nachricht wird stattdessen angezeigt:

This script requires Python 3.6 or newer.

Natürlich funktioniert diese Lösung nur bei Unix-artigen Shells und nur, wenn das Skript direkt aufgerufen wird (z. B. ./script.py), und wenn die entsprechenden Berechtigungsbits für die Ausführung von Execute-Anweisungen gesetzt sind.

0
J-L

Sie können dies mit sys.hexversion oder sys.version_info überprüfen.

sys.hexversion ist nicht sehr benutzerfreundlich, da es sich um eine Hexadezimalzahl handelt. sys.version_info ist ein Tupel, also menschlicher.

Prüfen Sie mit sys.hexversion nach Python 3.6 oder neuer:

import sys, time
if sys.hexversion < 0x30600F0:
    print("You need Python 3.6 or greater.")
    for _ in range(1, 5): time.sleep(1)
    exit()

Prüfen Sie mit sys.version_info nach Python 3.6 oder neuer:

import sys, time
if sys.version_info[0] < 3 and sys.version_info[1] < 6:
    print("You need Python 3.6 or greater.")
    for _ in range(1, 5): time.sleep(1)
    exit()

sys.version_info ist menschenfreundlicher, benötigt aber mehr Zeichen. Ich würde sys.hexversion empfehlen, auch wenn es weniger menschenfreundlich ist.

Ich hoffe das hat dir geholfen!

0
Pb2007