Was ist PyPy? Schnelleres Python ohne Schmerzen

Python hat sich den Ruf erarbeitet, leistungsstark, flexibel und einfach zu handhaben zu sein. Diese Tugenden haben zu seiner Verwendung in einer großen und wachsenden Vielfalt von Anwendungen, Workflows und Bereichen geführt. Das Design der Sprache - ihre interpretierte Natur, ihre Laufzeitdynamik - bedeutet jedoch, dass Python immer um eine Größenordnung langsamer war als maschinell native Sprachen wie C oder C ++.

Im Laufe der Jahre haben Entwickler eine Reihe von Problemumgehungen für die Geschwindigkeitsbeschränkungen von Python entwickelt. Sie können beispielsweise leistungsintensive Aufgaben in C schreiben und mit Python umschließen. Viele Bibliotheken für maschinelles Lernen tun genau dies. Oder Sie können Cython verwenden, ein Projekt, mit dem Sie Python-Code mit Informationen zum Laufzeit-Typ bestreuen können, mit denen er nach C kompiliert werden kann.

Problemumgehungen sind jedoch niemals ideal. Wäre es nicht großartig, wenn wir einfach ein vorhandenes Python-Programm so wie es ist nehmen und es dramatisch schneller ausführen könnten  ? Genau das können Sie mit PyPy tun.

Zugehöriges Video: Verwenden der PyPy-Laufzeit für Python

PyPy gegen CPython

PyPy ist ein Ersatz für den Standard-Python-Interpreter CPython. Während CPython Python zu einem Zwischenbytecode kompiliert, der dann von einer virtuellen Maschine interpretiert wird, verwendet PyPy die Just-in-Time-Kompilierung (JIT), um Python-Code in eine maschinen-native Assemblersprache zu übersetzen.

Abhängig von der ausgeführten Aufgabe können die Leistungssteigerungen dramatisch sein. Im Durchschnitt beschleunigt PyPy Python um das 7,6-fache, wobei einige Aufgaben um das 50-fache oder mehr beschleunigt werden. Der CPython-Interpreter führt einfach nicht die gleichen Optimierungen wie PyPy durch und wird dies wahrscheinlich auch nie tun, da dies nicht eines seiner Entwurfsziele ist.

Das Beste daran ist, dass der Entwickler nur wenig bis gar keine Anstrengungen unternehmen muss, um die von PyPy bereitgestellten Gewinne freizuschalten. Tauschen Sie CPython einfach gegen PyPy aus und schon sind Sie fertig. Es gibt einige Ausnahmen, die weiter unten erläutert werden. PyPys erklärtes Ziel ist es jedoch, vorhandenen, nicht modifizierten Python-Code auszuführen und ihn automatisch zu beschleunigen.

PyPy unterstützt derzeit sowohl Python 2 als auch Python 3 über verschiedene Inkarnationen des Projekts. Mit anderen Worten, Sie müssen abhängig von der Version von Python, die Sie ausführen, verschiedene Versionen von PyPy herunterladen. Der Python 2-Zweig von PyPy gibt es schon viel länger, aber die Python 3-Version wurde in letzter Zeit auf den neuesten Stand gebracht. Derzeit werden sowohl Python 3.5 (Produktionsqualität) als auch Python 3.6 (Beta-Qualität) unterstützt.

PyPy unterstützt nicht nur die gesamte Kernsprache von Python, sondern arbeitet auch mit den meisten Tools im Python-Ökosystem, z. B.  pip zum Verpacken oder  virtualenv für virtuelle Umgebungen. Die meisten Python-Pakete, auch solche mit C-Modulen, sollten unverändert funktionieren, obwohl es Einschränkungen gibt, auf die wir weiter unten eingehen werden.

Wie PyPy funktioniert

PyPy verwendet Optimierungstechniken, die in anderen Just-in-Time-Compilern für dynamische Sprachen zu finden sind. Es analysiert laufende Python-Programme, um die Typinformationen von Objekten zu ermitteln, die erstellt und in Programmen verwendet werden, und verwendet diese Typinformationen dann als Leitfaden, um die Dinge zu beschleunigen. Wenn eine Python-Funktion beispielsweise nur mit einem oder zwei verschiedenen Objekttypen arbeitet, generiert PyPy Maschinencode, um diese speziellen Fälle zu behandeln.

Die Optimierungen von PyPy werden zur Laufzeit automatisch ausgeführt, sodass Sie die Leistung im Allgemeinen nicht optimieren müssen. Ein fortgeschrittener Benutzer kann mit den Befehlszeilenoptionen von PyPy experimentieren, um für Sonderfälle schnelleren Code zu generieren. Dies ist jedoch nur selten erforderlich.

PyPy weicht auch von der Art und Weise ab, wie CPython einige interne Funktionen handhabt, versucht jedoch, kompatibles Verhalten beizubehalten. Beispielsweise behandelt PyPy die Speicherbereinigung anders als CPython. Nicht alle Objekte werden sofort erfasst, sobald sie den Gültigkeitsbereich verlassen. Daher weist ein Python-Programm, das unter PyPy ausgeführt wird, möglicherweise einen größeren Speicherbedarf auf als unter CPython. Aber man kann immer noch Python High-Level - Garbage - Collection - Kontrollen durch das offen liegende verwenden gcModul, wie gc.enable(), gc.disable()und gc.collect().

Wenn Sie Informationen zum JIT-Verhalten von PyPy zur Laufzeit wünschen, enthält PyPy ein Modul, pypyjitdas viele JIT-Hooks für Ihre Python-Anwendung verfügbar macht. Wenn Sie eine Funktion oder ein Modul haben, die mit der JIT anscheinend schlecht funktioniert, pypyjitkönnen Sie detaillierte Statistiken darüber abrufen.

Ein anderes PyPy-spezifisches Modul __pypy__stellt andere PyPy-spezifische Funktionen zur Verfügung und kann daher zum Schreiben von Apps nützlich sein, die diese Funktionen nutzen. Aufgrund der Laufzeitdynamik von Python ist es möglich, Python-Apps zu erstellen, die diese Funktionen verwenden, wenn PyPy vorhanden ist, und sie zu ignorieren, wenn dies nicht der Fall ist.

PyPy-Einschränkungen

Magisch wie PyPy scheinen mag, ist es keine Magie. PyPy weist bestimmte Einschränkungen auf, die seine Wirksamkeit für bestimmte Arten von Programmen verringern oder verhindern. Leider ist PyPy kein universeller Ersatz für die Standard-CPython-Laufzeit.

PyPy funktioniert am besten mit reinen Python-Apps

PyPy hat mit „reinen“ Python-Anwendungen immer die beste Leistung erbracht - dh mit Anwendungen, die in Python geschrieben wurden, und sonst nichts. Python-Pakete, die mit C-Bibliotheken wie NumPy verbunden sind, haben sich aufgrund der Art und Weise, wie PyPy die nativen binären Schnittstellen von CPython emuliert, nicht so gut geschlagen. 

Die Entwickler von PyPy haben dieses Problem behoben und PyPy mit den meisten Python-Paketen kompatibler gemacht, die von C-Erweiterungen abhängen. Numpy zum Beispiel funktioniert jetzt sehr gut mit PyPy. Wenn Sie jedoch maximale Kompatibilität mit C-Erweiterungen wünschen, verwenden Sie CPython.

PyPy funktioniert am besten mit länger laufenden Programmen

Einer der Nebeneffekte bei der Optimierung von Python-Programmen durch PyPy besteht darin, dass länger laufende Programme am meisten von den Optimierungen profitieren. Je länger das Programm läuft, desto mehr Informationen zum Laufzeittyp kann PyPy sammeln und desto mehr Optimierungen können vorgenommen werden. Einmalige Python-Skripte werden von solchen Dingen nicht profitieren. Die Anwendungen, die davon profitieren, verfügen normalerweise über Schleifen, die über einen längeren Zeitraum oder kontinuierlich im Hintergrund ausgeführt werden, z. B. Web-Frameworks.

PyPy kompiliert nicht vorab

PyPy  kompiliert  Python-Code, ist jedoch kein  Compiler  für Python-Code. Aufgrund der Art und Weise, wie PyPy seine Optimierungen durchführt, und der inhärenten Dynamik von Python gibt es keine Möglichkeit, den resultierenden JITted-Code als eigenständige Binärdatei auszugeben und wiederzuverwenden. Jedes Programm muss für jeden Lauf kompiliert werden. Wenn Sie Python in schnelleren Code kompilieren möchten, der als eigenständige App ausgeführt werden kann, verwenden Sie Cython, Numba oder das derzeit experimentelle Nuitka-Projekt.