Donnerstag, 23. Juni 2011

Deprecations zwischen Python 2.7 und 3.x

Eine kürzliche Diskussion auf python-dev zeigte ein Problem mit Pythons momentaner Verfahrensweise bezüglich Deprecations auf, das Entwickler betrifft, die von Python 2.7 auf aktuelle Versionen von Python 3.x umsteigen. Aufgrund dieses Problems hat das Entwickler-Team die aktuelle Deprecation-Policy angepasst, um die Tatsache zu berücksichtigen, dass Python-Nutzer normalerweise direkt von Python 2.7 auf die letzte Version von 3.x umsteigen, ohne je ältere Versionen gesehen zu haben.

Hintergrund

Python hat ein starkes Bekenntnis zur Rückwärtskompatibilität. Keine Veränderung ist erlaubt, ohne dass sie den Kompatibilitätsrichtlinien entspricht, was im Grunde heißt, dass korrekte Programme auch unter neuen Python-Versionen korrekt laufen. Aber das ist nicht immer möglich, beispielsweise wenn eine API klar kaputt ist und durch etwas anderes ersetzt werden muss. In dem Fall verfolgt Python eine Deprecation-Policy, die besagt, dass zu entfernende Features in einem einjährigen Übergangszeitraum formell deprecated werden. In diesem Übergangszeitraum muss eine DeprecationWarning ausgegeben werden, um den Entwicklern Zeit zu geben ihren Code zu aktualisieren. PEP 5 beschreibt die vollen Details von Pythons Deprecation-Policy. Da Veränderungen nur in neuen Python-Releases gemacht werden und es normalerweise eine 18-monatige Lücke zwischen Releases gibt, bedeutet das, dass dieser Zeitraum normalerweise einem Release entspricht.

Die eine Ausnahme zu dieser Verfahrensweise war Python 3. Der große Versionssprung zwischen Python 2 und Python 3 war genau dazu gedacht Veränderungen zu machen, die die Rückwärtskompatibilität brechen, um den Python-Entwicklern die Möglichkeit zu geben Probleme zu beheben, die einfach nicht innerhalb der Verfahrensweise behoben werden konnten. Zum Beispiel Strings standardmäßig zu Unicode zu machen und Iteratoren statt Listen zurückzugeben.

Parallele Entwicklungszweige

Wohlwissend, dass der Übergang nach Python 3 Zeit brauchen würde, nach vielen Schätzungen 5 Jahre, gab es in einigem Umfang eine parallele Entwicklung von Python 2 und 3.

Da Python 2.7 der letzte Release von Python 2 sein wird, wurde vereinbart, dass hier der Wartungszeitraum erheblich ausgedehnt wird. Letztlich müssen Entwickler, die zu einer neueren Version von Python wechseln wollen, also den Sprung nach Python 3 machen.

Und genau hier liegt das Problem ...

Überraschungsdeprecations

In einem Thread auf python-dev, wurde darauf hingewiesen, dass eine spezifische Funktion der C-API, PyCObject_AsVoidPtr, entfernt wurde, ohne dass davor ausreichend gewarnt wurde. Und doch soll die Deprecation-Policy genau das verhindern! Was ist also passiert?

Die Änderung war Teil einer größeren Migration von einer älteren API (PyCObject) zu einer neueren und verbesserten API (PyCapsule). Das Problem ist, dass PyCObject die Standard-API war und sogar die einzige in Python 2.6 verfügbare. Das API wurde in Python 2.7 deprecated. In Python 3.2 gibt es sie nicht und PyCapsule sollte genutzt werden. Damit gibt es einen Übergangszeitraum vom Release von Python 2.7 (Juli 2010) bis zum Release von Python 3.2 (Februar 2011), also knapp 7 Monate. Das ist erheblich weniger als der 12-Monate-Mindestzeitraum und macht es Entwicklern schwer eine sinnvolle Auswahl von Python-Releases zu unterstützen.

Für jemandem, der von 3.0 zu 3.1 und danach zu 3.2 wechselt, ist der Übergang in Ordnung. Python 3.1 wurde im März 2010 mit der Deprecation veröffentlicht und so gab es in der Python 3.x-Serie einen Übergangszeitraum von fast 12 Monaten. Allerdings ist das nicht, was Entwickler normalerweise tun: Sie gehen von Python 2.7 direkt zur letzten Version von Python 3.x, in diesem Fall Python 3.2, und schaffen so das Problem. Dies war nie die Absicht von python-dev, aber beim Schreiben von PEP 5 wurde nicht an zwei parallele Versionen gedacht, die beide aktiv entwickelt wurden.

Was machen wir also?

Auch wenn der PyCObject/PyCapsule-API-Bruch ein echtes Problem ist, so ist es nicht unmöglich es zu umgehen, aber mindestens ein Poster hatte auf python-dev Schwierigkeiten damit. Insgesamt hätte das nie passieren dürfen.

Für den speziellen Fall von PyCObject/PyCapsule gibt es das Problem schon und es kann nicht viel dagegen getan werden. PyCObject wieder einzusetzen stand nicht wirklich zur Debatte, da es nur noch mehr Inkompatibilitäten schaffen würde. Jedoch war die allgemeine Ansicht, dass es möglich, wenn auch mühsam, wäre Code zu schreiben, der sich jeder verfügbaren API anpassen könnte. In der Tat war in Python 3.1 die PyCObject-API nur eine Schicht auf der PyCapsule-API. Es gab auch den Vorschlag, dass man falls nötig die Python 3.1 Implementierung extrahieren und als Dritt-Modul anbieten könnte. Man war sich einig, dass man ein "rückwirkendes" PEP schreiben würde, um die Gründe hinter der Veränderung zu beschreiben und Ressourcen zu dokumentieren, die Entwicklern beim Umstieg helfen können.

Allgemein gesprochen ist das Python-Entwicklungsteam nun mit dem Problem vertraut und wird daran arbeiten, dass es nicht wieder passieren wird. Guido veröffentlichte eine Überprüfung der Situation und schlug vor, dass man für den Moment in Python 3 sparsam mit Deprecations umgehen sollte. Mindestens sollten deprecated APIs erheblich länger behalten werden, bevor sie entfernt werden, um von Python 2.7 kommenden Entwicklern einen Migrationspfad zu bieten.

Indirekter wurde in dem Thread auch das Problem behandelt wie man effektiver Veränderungen in Python zeitnaher und einem breiterem Kreis kommunizieren könnte -- genau die Art von Problem also, für die dieses Blog geschaffen wurde.

Was bedeutet das alles?

In erster Linie bedeutet das, dass die Python-Entwickler nicht immer alles richtig machen. Niemand wollte den Entwicklern das Leben schwer machen, sondern es war einfach ein Problem, das nicht rechtzeitig entdeckt wurde.

Zweitens, dass das Beheben des Problems mehr Schaden als Nutzen kann, weshalb das PyCObject-API nicht wieder eingesetzt wurde. Zwar würde das Entwicklern helfen, die von der Veränderung gebissen wurden, aber zu dem Preis, dass Kompatibilitätsprobleme komplexer würden. In der Zwischenzeit müssen wir mit dem Problem leben und weiter machen. Lehren wurden daraus gezogen und wir werden den Fehler nicht nochmal machen.

Dies zeigt auch, dass das Python-Entwicklerteam von seinen Anwendern hören will. Kompatibilität ist wichtig und es wird alles daran gesetzt den Übergang zu neuen Versionen so schmerzlos wie möglich zu machen. Besonders Bibliotheken-Entwickler sollten mit einem angemessenen Maß an Aufwand mehrere Python-Versionen unterstützen können.

Schließlich heißt das: Entwickler haben Python 2.7 noch nicht verlassen. Obwohl es keine neue Features und kein Python 2.8 geben wird, sind die Ansichten der Python 2.7-Nutzer dennoch wichtig. Es ist wesentlich für die gesamte Python-Community, sicherzustellen, dass Nutzer zu 3.x wechseln können, wenn sie bereit sind.

Englische Version

Keine Kommentare:

Kommentar veröffentlichen