43.2 Automatische Konvertierung 

Um die Migration von Python 2 nach Python 3 auch bei größeren Projekten zu vereinfachen, gibt es in der Python-3-Distribution ein Tool namens 2to3, das wir Ihnen in diesem Abschnitt vorstellen möchten. Das Tool 2to3 finden Sie im Unterverzeichnis Tools/scripts Ihrer Python-Distribution.
Die Verwendung von 2to3 wird exemplarisch an folgendem Python-2-Beispielprogramm demonstriert:
def getInput(n):
liste = []
for i in xrange(n):
try:
z = int(raw_input("Bitte eine Zahl eingeben: "))
except Exception, e:
raise ValueError("Das ist keine Zahl!")
liste.append(z)
return liste
try:
res = getInput(5)
print res
except ValueError, e:
print e.args[0]
Dieses Programm liest mithilfe der Funktion getInput fünf Zahlen vom Benutzer ein und gibt eine mit diesen Zahlen gefüllte Liste aus. Wenn der Benutzer etwas eingibt, was keine Zahl ist, beendet sich das Programm mit einer Fehlermeldung. Sie sehen sofort, dass sich dieses Programm so nicht unter Python 3 ausführen lässt. Die Aufrufe von xrange, raw_input sowie die beiden except-Anweisungen verhindern dies.
Bereits bei den oben dargestellten 14 Quellcodezeilen ist es mühselig, den Code per Hand mit Python 3 kompatibel zu machen. Stellen Sie sich diese Arbeit einmal für ein größeres Projekt vor! Doch glücklicherweise gibt es 2to3. Wir rufen 2to3 einmal mit dem Namen unseres Python-Programms als einzigem Parameter auf. Das Ergebnis sieht folgendermaßen aus:
--- test.py (original)
+++ test.py (refactored)
@@ -1,15 +1,15
def getInput(n):
liste = []
- for i in xrange(n):
+ for i in range(n):
try:
- z = int(raw_input("Bitte eine Zahl eingeben: "))
- except ValueError, e:
+ z = int(input("Bitte eine Zahl eingeben: "))
+ except ValueError as e:
raise ValueError("Das ist keine Zahl!")
liste.append(z)
return liste
try:
res = getInput(5)
- print res
-except ValueError, e:
- print e.args[0]
+ print(res)
+except ValueError as e:
+ print(e.args[0])
Das Konvertierungsprogramm ändert Ihre angegebenen Quellcodedateien standardmäßig nicht, sondern produziert nur einen diff-Ausdruck. Das ist eine spezielle Beschreibungssprache für die Unterschiede zwischen zwei Textstücken. Diesen diff-Ausdruck können Sie beispielsweise mithilfe des Unix-Programms patch in Ihre Quelldatei einpflegen. Alternativ erlauben Sie es dem 2to3-Skript über den Kommandoschalter -w, die angegebene Quelldatei direkt zu modifizieren. Der ursprüngliche Python-2-Code wird dabei als dateiname.py.bak gesichert. Wenn 2to3 mit dem Schalter -w und unserem oben dargestellten Beispielquellcode gefüttert wird, sieht der konvertierte Code hinterher so aus:
def getInput(n):
liste = []
for i in range(n):
try:
z = int(eval(input("Bitte eine Zahl eingeben: ")))
except Exception as e:
raise ValueError("Das ist keine Zahl!")
liste.append(z)
return liste
try:
res = getInput(5)
print(res)
except ValueError as e:
print(e.args[0])
Sie sehen, dass die eingangs angesprochenen Stellen geändert wurden, und werden feststellen, dass der übersetzte Code unter Python 3 lauffähig ist.
Anstelle einer einzelnen Programmdatei können Sie dem 2to3-Skript auch eine Liste von Dateien oder Ordnern übergeben. Wenn Sie einen Ordner übergeben haben, wird jede Quelldatei in ihm oder einem seiner Unterordner konvertiert.
Zum Schluss möchten wir noch auf die wichtigsten Kommandozeilenschalter zu sprechen kommen, mit deren Hilfe Sie das Verhalten von 2to3 an Ihre Bedürfnisse anpassen können:
Schalter | Alternativ | Beschreibung |
---|---|---|
-d | --doctests_only | Ist dieser Schalter gesetzt, werden ausschließlich die in der angegebenen Quelldatei enthaltenen Doctests nach Python 3 konvertiert. Standardmäßig werden Doctests nicht angerührt. Näheres über Doctests erfahren Sie in Abschnitt 35.4.1. |
-f FIX | --fix=FIX | Mit dieser Option geben Sie vor, welche sogenannten Fixes angewandt werden sollen. Bei einem Fix handelt es sich um eine bestimmte Ersetzungsregel, beispielsweise das Ersetzen von xrange durch range. |
-x NOFIX | --nofix=NOFIX | Das Gegenstück zu -f. Hier bestimmen Sie, welche Fixes nicht angewandt werden dürfen. |
-l | --list-fixes | Durch Setzen dieses Schalters erhalten Sie eine Liste aller verfügbaren Fixes. |
-p | --print-function |
Wenn dieser Schalter gesetzt ist, werden print-Anweisungen nicht konvertiert. Das ist nützlich, wenn Sie print bereits in Python 2.6 wie eine Funktion geschrieben oder den entsprechenden Future Import print_function eingebunden haben. Das Programm 2to3 kann nicht von selbst entscheiden, ob es eine print-Anweisung mit Klammern versehen muss oder nicht. |
-w | --write | Ist dieser Schalter gesetzt, werden die Änderungen direkt in die untersuchte Quelldatei geschrieben. Ein Backup wird unter dateiname.py.bak angelegt. |
-n | --nobackups | Wenn dieser Schalter gesetzt ist, wird auf das Anlegen der Backup-Datei verzichtet. |
Tabelle 43.11 Kommandozeilenoptionen von 2to3