Zu Python 2.7 migrieren

Auf dieser Seite werden die Maßnahmen beschrieben, die zum Aktualisieren Ihrer Python-Anwendung auf die Python 2.7-Laufzeit erforderlich sind. Nachdem Sie diese Schritt-für-Schritt-Anleitung durchgearbeitet haben, kann Ihre Anwendung die vielen neuen Funktionen der Python 2.7-Laufzeit nutzen, einschließlich Multithreading, Jinja2-Vorlagen-Engine, Bytecode-Zugriff und -Uploads sowie mehrerer neuer integrierter Drittanbieterbibliotheken.

Voraussetzungen und Hinweise

Eine Anwendung muss folgende Anforderungen erfüllen, um Python 2.7 verwenden zu können:

  • Wenn die Anwendung Django nutzt, muss sie Version ab 1.2 verwenden. Upgradeinformationen finden Sie unter Django-Dokumentation.
  • Wenn Sie gleichzeitige Requests verwenden möchten, muss die Anwendung WSGI-Skript-Handler (Web Server Gateway Interface) verwenden, wie unter WSGI verwenden beschrieben.

Neben der Erfüllung dieser allgemeinen Voraussetzungen müssen Sie auch bestimmte Versionen einiger App Engine-Funktionen und Drittanbieterbibliotheken verwenden. Aktualisieren Sie unbedingt die Versionen, die Sie in Ihre Anwendung integrieren und importieren, und testen Sie die Anwendung nach dem Upgrade ausgiebig. Nachfolgend sind die wichtigsten Kompatibilitätsprobleme aufgeführt und es wird auf weitere Ressourcen zum Beheben der Probleme verwiesen:

  • Performance: Die Anwendungsleistung kann sich nach dem Upgrade auf Python 2.7 ändern. Wenn sich die Antwortlatenz erhöht, können Sie die Frontend-Instanzklasse erhöhen und gleichzeitige Anfragen aktivieren. Gleichzeitige Requests ermöglichen eine schnellere Ausführung der Anwendung mit niedrigeren Instanzkosten bei größeren Instanzen. Weitere Informationen finden Sie unter Anfrageverarbeitung in Instanzen.
  • Django: Sie müssen Django ab 1.2 mit Python 2.7 verwenden. Upgradeinformationen finden Sie in den Django-Versionshinweisen.
  • PyCrypto: Crypto.Util.randpool wurde zugunsten von Crypto.Random verworfen. Weitere Informationen finden Sie unter Vorgehensweise zu RandomPool.
  • webapp: webapp-Vorlagen wurden in Python 2.7 verworfen. Stattdessen können Sie Django-Vorlagen direkt oder jinja2 oder eine andere Vorlagen-Engine Ihrer Wahl verwenden.
  • WebOb: Python 2.7 unterstützt WebOb Version 1.1. Diese Version ist mit der alten Version (0.9) nicht vollständig abwärtskompatibel. Wenn die Anwendung WebOb verwendet, müssen Sie sie ausgiebig testen, um jegliche Fehler zu erkennen, die aus dem Upgrade resultieren.
  • zipimport: Python 2.7 unterstützt zipimport nicht, kann jedoch nativ aus ZIP-Dateien importieren.
  • simplejson: Python 2.7 unterstützt simplejson nicht, enthält jedoch das entsprechende und viel schnellere json-Modul der Standardbibliothek.

Gleichzeitige Requests und WSGI

Die Python 2.7-Funktion, die sich am meisten auf das Design und die Leistung Ihrer Anwendung auswirkt, ist die Unterstützung von Multithread-Anwendungen, die gleichzeitige Requests verarbeiten können. Die Fähigkeit zur Verarbeitung gleichzeitiger Requests führt zu einer verbesserten Auslastung, die die Leistung Ihrer Anwendung erheblich verbessern kann – insbesondere bei Anwendungen mit höheren Instanzklassen, die mehrere CPU-Kerne nutzen.

Anwendungen müssen von dem auf CGI (Common Gateway Interface) basierenden Ansatz der vorherigen Python-Laufzeiten zu einem auf WSGI (Web Server Gateway Interface) basierenden Ansatz wechseln, um Multithreading zu ermöglichen. Der Grund hierfür ist, dass CGI-Skripts, die für die aufeinanderfolgende Verarbeitung von Requests konzipiert wurden, für den Zugriff auf die Ein- und Ausgabestreams Umgebungsvariablen nutzen.

Das WSGI-Modell zur Verarbeitung von Requests gibt Anwendungen direkteren Zugriff auf die Ein- und Ausgabestreams (was gleichzeitige Requests ermöglicht). Die parallele Verarbeitung mehrerer Requests kann jedoch Race-Bedingungen verursachen, wenn die Logik eines Request-Handlers Daten, deren Bereich nicht nur lokal ist, nutzt oder mit ihnen interagiert, z. B. den Anwendungsstatus. Deshalb ist es wichtig, defensiv zu codieren, was Race-Bedingungen angeht, um sicherzustellen, dass die neue WSGI-Anwendung threadsicher ist.

Weitere Informationen finden Sie unter Anwendungen threadsicher machen.

app.yaml aktualisieren

Python 2.7 benötigt ein spezielles runtime-Konfigurationselement im Header von app.yaml. Beachten Sie, dass das Element threadsafe: [ true | false ] für Python 2.7-Anwendungen erforderlich ist. Bei true sendet App Engine Anfragen gleichzeitig; bei false sendet App Engine sie nacheinander. Der folgende app.yaml-Header ermöglicht gleichzeitige Anfragen:

application: myapp
version: 1
runtime: python27
api_version: 1
threadsafe: true
...

WSGI verwenden

Die Python 2.7-Laufzeit ermöglicht optional das direkte Ausführen einer WSGI-Anwendung (Web Server Gateway Interface), anstatt den Adapter run_wsgi_app zum Ausführen des Programms als CGI-Skript zu verwenden. Ersetzen Sie dazu den CGI-Handler (z. B. myapp.py) in app.yaml durch einen WSGI-Anwendungsnamen (z. B. myapp.app).

...
handlers:
- url: /.*
  script: myapp.app
...

Sie müssen auch Ihr WSGI-Anwendungsobjekt in den globalen Bereich verschieben:

import webapp2

class MainPage(webapp2.RequestHandler):
  def get(self):
    self.response.headers['Content-Type'] = 'text/plain'
    self.response.out.write('Hello, WebApp World!')

app = webapp2.WSGIApplication([('/', MainPage)])

""" Old code:
def main():
  run_wsgi_app(app)

if __name__ == '__main__':
  main()
"""

Sie können weiterhin CGI-Skript-Handler in app.yaml angeben. Anfragen, die von CGI-Skripts verarbeitet werden, werden jedoch nacheinander, nicht gleichzeitig verarbeitet. Außerdem können Sie keine app.yaml-Datei verwenden, die CGI-Skripts und WSGI-Anwendungen mischt, und Sie können threadsafe nicht auf true festlegen, falls Sie CGI-Handler definieren.

Einige Konventionen aus vorherigen Python-Laufzeiten, wie die Verwendung von main() und die Prüfung von __name__ == 'main', wurden verworfen. Diese Maßnahmen trugen in der Vergangenheit dazu bei, dass die CGI-Skripts im Cache gespeichert blieben. Nun, da Sie WSGI-Anwendungen direkt ausführen, sind diese Schritte nicht mehr notwendig.

Stammverzeichnis der Anwendung verwenden

In Python 2.5 war bei der Ausführung von CGI-Skripts das aktuelle Arbeitsverzeichnis auf das Verzeichnis festgelegt, das das Skript enthielt. Das hat sich in Python 2.7 geändert. Bei WSGI ist das aktuelle Arbeitsverzeichnis zu Beginn des Lebenszyklus des Request-Handlers das Stammverzeichnis der Anwendung.

Überprüfen Sie Ihren Anwendungscode und sorgen Sie dafür, dass alle Handler so geschrieben sind, dass sie das Stammverzeichnis der Anwendung als aktuelles Arbeitsverzeichnis erwarten.

Bibliotheken konfigurieren

Die Python 2.7-Laufzeit enthält einige Module von Drittanbietern. Einige davon sind standardmäßig verfügbar. Andere sind nur verfügbar, wenn sie konfiguriert werden. Sie können angeben, welche Version Sie verwenden möchten.

libraries:
- name: PIL
  version: "1.1.7"
- name: webob
  version: "1.1.1"

Sie können angeben, dass die Anwendung die neueste Version des Moduls verwenden soll. Dies ist nützlich, wenn Sie eine Anwendung entwickeln, für die noch keine Nutzer vorhanden sind: Sie brauchen neue Versionen nicht kontrollieren. Wenn Ihre Anwendung jedoch aktiv genutzt wird, geben Sie acht: Möglicherweise stellen Sie überrascht fest, dass Ihre Anwendung beginnt, eine neue, nicht abwärtskompatible Version der Bibliothek zu verwenden. So verwenden Sie die neueste Version:

libraries:
- name: PIL
  version: latest

Eine Liste der unterstützten Bibliotheken finden Sie unter Bibliotheken von Drittanbietern.

Anwendungen threadsicher machen

Die Verarbeitung gleichzeitiger Requests ist einfach, wenn jeder Handler nur mit Variablen innerhalb seines Bereichs interagiert. Aber es wird schnell schwierig, wenn ein Handler Ressourcen ändert, während ein anderer sie liest. Dafür zu sorgen, dass Ihre Anwendung sich wie erwartet verhält – auch wenn mehrere Requests dieselben Daten bearbeiten und sich gegenseitig in die Quere kommen – wird auch als "die Anwendung threadsicher machen" bezeichnet.

Die wichtigste Regel beim Auslegen einer Anwendung auf Threadsicherheit ist, die Verwendung gemeinsam genutzter Ressourcen (z. B. Statusinformationen oder globale Variablen) so weit wie möglich einzuschränken. Es ist jedoch normalerweise nicht möglich, ihre Verwendung vollständig auszuschließen. Hier kommen Synchronisierungsmechanismen wie Sperrobjekte ins Spiel.

In Python 2.7 haben Sie Zugriff auf die Threading-Bibliothek von Python, mit der Sie eine Sperre für einen Logikblock deklarieren können, die den Code zwingt, nacheinander anstatt gleichzeitig ausgeführt zu werden. Betrachten wir den folgenden Code:

class Configuration(ndb.Model):
  some_config_data = ndb.StringProperty()
  _config_cache = None
  _config_lock = threading.Lock()
  @classmethod
  def get_config(cls):
    with cls._config_lock:
      if not cls._config_cache:
        cls._config_cache = cls.get_by_id('config')
    return cls._config_cache

Dieser Code zeigt die Erstellung eines Caches einiger globaler Konfigurationsvariablen in einer Variablen namens "_config_cache". Hier sorgt die Verwendung eines Sperrobjekts "namens" _config_lock dafür, dass die Prüfung auf einen bereits vorhandenen _config_cache zuverlässig funktioniert. Ansonsten könnte diese Variable Zeit verschwenden, indem sie mehrere Zugriffe auf den Datastore unternimmt, um ein und dieselbe Variable mehrmals mit denselben Daten festzulegen, da die konkurrierenden Anfragen alle festgestellt haben, dass _config_cache leer ist.

Überlegen Sie sich gut, Sperren zu verwenden. Eine Sperre blockiert alle anderen Threads, die diese Methode ausführen. Das kann zum Leistungsengpass werden.

Anwendung auf webapp2 aktualisieren

Hinweis: Wenn Sie nicht webapp als Ihren Anfrage-Handler verwenden, können Sie diesen Abschnitt überspringen.

Für das in der Python 2.7-Laufzeit enthaltene Web-Framework wurde ein Upgrade von webapp auf webapp2 durchgeführt. webapp2 bietet u. a. verbessertes URI-Routing und verbesserte Ausnahmebehandlung, ein Antwortobjekt mit vollem Funktionsumfang und einen flexibleren Verteilungsmechanismus.

webapp-Vorlagen wurden eingestellt. An ihrer Stelle können Sie Jinja2, Django oder ein Vorlagensystem Ihrer Wahl verwenden, wenn es in reinem Python geschrieben ist.

In App Engine wird webapp2 als Alias für webapp verwendet und webapp2 ist abwärtskompatibel. Nach dem Upgrade müssen Sie Ihre Anwendung jedoch gründlich testen und sich mit der neuen Syntax und den neuen Funktionen von webapp2 vertraut machen, um nicht von der Abwärtskompatibilität abhängig zu sein.

Ihr Upgrade ist nun abgeschlossen!

Nachdem Sie die Anwendung hochgeladen haben, müssen Sie sie ausgiebig testen, um die Abwärtskompatibilität sicherzustellen. Falls Probleme auftreten, finden Sie Informationen in den Foren.