2009-12-09 20 views
8

Dieses Thema hat mich seit einiger Zeit gestört.Unterstützung verschiedener Versionen von Python

Für my Python project Ich wollte in der Lage sein, Python-Versionen 2.4 bis 3.1 zu unterstützen. Ich dachte ein bisschen darüber nach, wie ich das machen könnte, und entschied mich schließlich, vier separate Forks des Quellcodes für vier verschiedene Versionen von Python zu haben: 2.4, 2.5, 2.6 und 3.1.

Ich bin gekommen, um das als eine schlechte Entscheidung, vor allem wegen Python Verteilung Ärgernisse, die ich jetzt vier Mal statt einer zu tun haben.

Die Frage ist, was zu tun ist?

Mein Projekt ist im Bereich der wissenschaftlichen Datenverarbeitung. Ich habe den Eindruck, dass es immer noch viele Leute gibt, die auf Python 2.4 angewiesen sind.

Jemand schlug vor, ich schreibe mein ganzes Projekt für 2.4, aber das ist inakzeptabel für mich. Das bedeutet, dass ich keine Kontextmanager verwenden kann, und darauf werde ich nicht verzichten.

Wie unterstützen normale Python-Projekte 2.4? Vermeiden sie die Verwendung von Kontextmanagern?

Gibt es auch eine andere Option als Python 3.1? Ich weiß, dass es alle Arten von Hacks gibt, um denselben Code auf 2.x und 3.x laufen zu lassen, aber einer der Gründe, warum ich Python mag, ist, dass der Code schön ist und ich es nicht tolerieren werde, ihn mit Kompatibilitäts-Hacks hässlich zu machen.

Bitte geben Sie mir Ihre Meinung.

Antwort

1

Ja, Sie müssen für Python 2.4-Syntax schreiben, um alle 2.4 - 2.7 in der gleichen Codebasis zu unterstützen.

Einige Änderungen in Python 2.6 und 2.7 sollen es leichter machen, kompatiblen Code mit 3.x zu schreiben, aber Sie müssen die Unterstützung für 2.5 und darunter fallen lassen, um das zu tun.

+0

Ich sehe. Ich bin bereit, Möglichkeiten zu erkunden, es nicht in der gleichen Codebasis zu tun. Genau das mache ich jetzt im Extremfall mit getrennten Gabeln für verschiedene Versionen. Vielleicht könnte ich es aber schlauer machen. –

0

Wenn die Unterschiede zwischen den Versionen nicht extrem sind, können Sie versuchen, sie in ein separates Paket oder Modul zu isolieren, in dem Sie versionsspezifischen Code schreiben, um als Anpassungsschicht zu fungieren.

In einfachen Fällen kann dies ohne das separate Modul in einfachen Fällen geschehen, beispielsweise wenn eine neue Version von Python standardmäßig ein Paket erstellt, das früher extern war, wie zum Beispiel simplejson. Wir haben etwas ähnliches wie dies in einigen Code:

try: 
    import simplejson as json 
except ImportError: 
    import json 

Für nicht-triviale Sachen, wie, was Sie wahrscheinlich haben, würden Sie nicht solche Dinge wollen zufällig über Ihren Code-Basis verstreut, so dass Sie es sammeln sollten alle Wenn möglich an einem Ort zusammen, und machen Sie das den einzigen Abschnitt Ihres Codes, der versionsspezifisch ist.

Dies kann nicht so gut für Dinge funktionieren, bei denen die Syntax anders ist, wie zum Beispiel Ihren Kommentar über die Verwendung von Kontextmanagern. Sicher, Sie könnten den Context-Manager-Code in ein separates Modul einfügen, aber das wird wahrscheinlich die Orte komplizieren, an denen Sie es verwenden würden. In solchen Fällen können Sie bestimmte kritische Funktionen (ich denke, Kontext-Manager könnten leicht simuliert werden) zu diesem Adaptermodul zurückportieren.

Auf jeden Fall mit separaten Codebasen ist über das Schlimmste, was Sie tun könnten, also würde ich sicherlich empfehlen, davon weg arbeiten.Zumindest nicht willkürlich Features aus neueren Versionen von Python verwenden, da obwohl es schön aussehen mag, sie im Code zu haben (vielleicht einen bestimmten Block von Logik zu vereinfachen), die Tatsache, dass Sie diese Logik kopieren müssen, indem Sie die Codebase, sogar auf einem einzigen Modul, wird die Vorteile mehr als negieren.

Wir bleiben bei älteren Versionen für Legacy-Code, Tweaking wie neue Releases herauskommen, um sie zu unterstützen, aber die Unterstützung für die älteren, manchmal mit kleinen Adapter-Schichten. Irgendwann zeigt sich eine große Version unseres Codes im Zeitplan, und wir überlegen, ob es an der Zeit ist, die Unterstützung für ein älteres Python fallen zu lassen. Wenn das passiert, versuchen wir, mehrere Versionen zu überspringen, indem wir (beispielsweise) direkt von 2.4 auf 2.6 gehen und erst dann anfangen, die neue Syntax und nicht anpassungsfähige Funktionen wirklich zu nutzen.

0

Zunächst müssen Sie daran denken, dass Python 2.x größtenteils die gleiche Syntax teilt, die rückwärtskompatibel ist, neue Funktionen & Ergänzungen beiseite. Es gibt andere Dinge zu beachten, die nicht unbedingt Fehler sind, wie DeprecationWarning-Nachrichten, die zwar nicht schädlich sind, aber hässlich sind und Verwirrung stiften können.

Python 3.x ist von vornherein INCompatible und beabsichtigt, den alten Kram hinter sich zu lassen. Python 2.6 führte viele Änderungen ein, die auch in Python 3.x enthalten sind, um den Übergang zu erleichtern. Um alle zu sehen, empfehle ich, das Dokument What's New in Python 2.6 zu lesen. Aus diesem Grund ist es sehr gut möglich, Code für Python 2.6 zu schreiben, der auch in Python 3.1 läuft, aber das ist nicht ohne Vorbehalte.

Sogar noch gibt es viele geringfügige Syntaxänderungen sogar zwischen 2.x-Versionen, die Sie benötigen, wickeln Sie viel von Ihrem Code in try/except Blöcke, also wenn Sie das wollen, dann haben Sie eine 2 .x und 3.x Zweig ist völlig möglich. Ich denke, Sie werden feststellen, dass Sie eine Menge von Attribut- und Typprüfungen an Ihren Objekten durchführen werden, um das zu tun, was Sie tun möchten.

Ich würde Ihnen empfehlen, den Code der großen Projekte heraus dort zu überprüfen, die verschiedene Python-Versionen unterstützen. Twisted Matrix ist der erste, der in den Sinn kommt. Ihr Code ist ein wunderbares Beispiel dafür, wie Python-Code geschrieben werden sollte.

Am Ende wird es nicht einfach sein, was Sie tun werden, also bereiten Sie sich auf eine Menge Arbeit vor!

+0

Wo haben Sie die verschiedenen Zweige für 2.4-2.6 gesehen? Ich habe verschiedene Binärdownloads für Windows gesehen, aber die Quelle scheint wie ein Ordner zu sein. Habe ich etwas vergessen? –

+0

'set' und' frozenset' wurden in ** Python 2.4 ** hinzugefügt. http://www.python.org/doc/2.4.4/whatsnew/whatsnew24.html – u0b34a0f6ae

+0

@ cool-RR - Nein, ich habe etwas verpasst. Ich habe die schlechten Informationen entfernt. @ kaizer.se - Danke, ich habe die 'sets'-Depretierung mit dem Hinzufügen der eingebauten Typen verwechselt. – jathanism

1

Es scheint verschiedene Antworten auf Ihr Problem zu geben.

Erstens, wenn Sie alle Funktionen anbieten wollen für alle Python-Versionen dann ja, sind Sie wahrscheinlich mit der Verwendung der kleinstmöglichen Funktionalität Teilmenge stecken - damit Ihr Code für Python 2.4 zu schreiben. Oder Sie können Funktionen neuere Interpreter rückportieren, wenn sie reine Pythons sind (das gilt nicht für Kontextmanager oder Coroutinen).

Oder Sie könnten Versionsunterstützung in Features aufteilen - wenn Sie denken, dass es eine (optionale) Funktion gibt, die von Context Managern profitieren würde, können Sie sie in einem separaten Modul zur Verfügung stellen Habe dieses Feature nicht.

Um Python 3 zu unterstützen, werfen Sie einen Blick auf den 2to3-Helfer. Wenn Sie Ihren Code richtig schreiben, besteht eine große Chance, dass Sie nicht zwei separate Codebasen pflegen müssen.

0

Sie könnten versuchen, virtualenv und verteilen Sie Ihre Anwendung mit einer einzigen Python-Version. Dies kann oder kann in Ihrem Fall jedoch nicht praktikabel sein.

0

Wir haben ein verwandtes Problem, ein großes System, das sowohl jython als auch cpython zurück auf 2.4 unterstützt.Im Grunde müssen Sie Code, der anders geschrieben werden muss, in eine hoffentlich kleine Gruppe von Modulen eingrenzen und die Dinge bedingt importieren lassen.

# module svn.py 
import sys 
if sys.platform.startswith('java'): 
    from jythonsvn import * 
else: 
    from nativesvn import * 

In Ihrem Beispiel würden Sie vermutlich Tests gegen sys.version_info verwenden. Sie könnten ein paar einfache Dinge in einem Versorgungsmodul definieren, dass Sie wie verwenden würden: von util import *

# module util.py 
import sys 
if sys.exc_info[0] == 2: 
    if sys.exc_info[1] == 4: 
     from util_py4 import * 
    ... 

Dann Dinge in util_py4.py wie: ein anderes Problem

def any(seq):    # define workaround functions where possible 
    for a in seq: 
     if a: return True 
    return False 
... 

Obwohl dies als Portieren (da Sie fortfahren möchten, zu unterstützen), gibt dieser Link einige nützliche Anleitung http://python3porting.com/preparing.html (wie auch eine Vielzahl anderer Artikel über die Portierung von Python 2.x).

Ihr Kommentar, dass Sie ohne Kontextmanager nicht leben können, ist ein wenig verwirrend. Während Kontext-Manager leistungsfähig sind und den Code lesbarer machen und das Risiko von Fehlern minimieren, können Sie sie einfach nicht im Code Ihrer 2.4-Version finden.

### 2.5 (with appropriate future import) and later 
with open('foo','rb')as myfile: 
    # do something with myfile 

### 2.4 and earlier 
myfile = None 
try: 
    myfile = open('foo','rb') 
    # do something with myfile 
finally: 
    if myfile: myfile.close() 

Da Sie 2.4 unterstützen möchten, haben Sie einen Code, der nur die zweite Syntax haben muss. Wird es wirklich eleganter sein, beides zu schreiben?

Verwandte Themen