Warum Python-Code kompilieren?

241

Warum sollten Sie ein Python-Skript kompilieren? Sie können sie direkt aus der .py-Datei ausführen und es funktioniert einwandfrei. Gibt es also einen Leistungsvorteil oder so?

Ich stelle auch fest, dass einige Dateien in meiner Anwendung in .pyc kompiliert werden, während andere dies nicht tun. Warum ist das so?

Ryeguy
quelle
Sie können auch feststellen, dass Sie, einschließlich des schnelleren Starts Ihrer Anwendung, auch an Sicherheit gewinnen, wenn Sie Ihren Code nicht freigeben können, wenn es sich um ein Unternehmensgeheimnis handelt.
Please_Dont_Bully_Me_SO_Lords
@PSyLoCKe Das tust du wirklich, wirklich nicht. Python-Bytecode ist wirklich lesbar, da der Compiler ihn nicht verschleiern muss, um ihn zu optimieren. (Nicht, dass es es viel optimiert ...)
wizzwizz4
1
Einige Dateien werden automatisch kompiliert, weil sie importiert werden. Wenn Sie beispielsweise verwenden import mylib.py, wird Python kompiliert, mylib.pysodass zukünftige importAnweisungen etwas schneller ausgeführt werden. Wenn Sie später ändern mylib.py, wird es beim nächsten Import neu kompiliert (Python verwendet das
Dateidatum, um

Antworten:

269

Es ist zu Bytecode kompiliert, der viel, viel, viel schneller verwendet werden kann.

Der Grund, warum einige Dateien nicht kompiliert werden, ist, dass das Hauptskript, mit dem Sie aufrufen, python main.pyjedes Mal neu kompiliert wird, wenn Sie das Skript ausführen. Alle importierten Skripte werden kompiliert und auf der Festplatte gespeichert.

Wichtiger Zusatz von Ben Blank :

Es ist erwähnenswert, dass während eines kompilierten Skript ausgeführt wird eine schnellere hat Startzeit (da es nicht kompiliert werden muss), es nicht laufen schneller.

Georg Schölly
quelle
259
Es ist erwähnenswert, dass während eines kompilierten Skript ausgeführt wird eine schnellere hat Startzeit (da es nicht kompiliert werden muss), es nicht laufen schneller.
Ben Blank
24
Ein häufiges Missverständnis. Danke für das Teilen.
Matpie
1
Die .pyc-Datei muss nicht nur nicht kompiliert werden, sondern ist auch fast immer kleiner. Vor allem, wenn Sie viel kommentieren. Einer von mir ist 28419 als .py, aber nur 17879 als .pyc - also ist auch die Ladezeit besser. Schließlich können Sie Skripte der obersten Ebene folgendermaßen vorkompilieren: python -m compileall myscript.py
fyngyrz
1
Gibt es einen Unterschied im Speicherverbrauch? Ich teste Python auf eingebetteten Geräten, die auf einer Mips-CPU mit nur 64 MB RAM basieren. Gibt es also einen Vorteil bei der Speichernutzung, wenn eine kompilierte Version des Python-Skripts gestartet wird?
Valentt
1
@valentt: Wahrscheinlich nicht. Ich weiß nicht viel über die Python-Interna, aber ich glaube nicht, dass das Parsen in Bytecode viel Speicher in Python beansprucht. Ich kann mir nichts vorstellen, das viel Gedächtnis braucht, um sich an einen Zustand zu erinnern.
Georg Schölly
80

Die .pyc-Datei ist Python, die bereits zu Bytecode kompiliert wurde. Python führt automatisch eine .pyc-Datei aus, wenn es eine mit demselben Namen wie eine von Ihnen aufgerufene .py-Datei findet.

"Eine Einführung in Python" sagt dies über kompilierte Python-Dateien:

Ein Programm wird beim Lesen aus einer '.pyc'- oder' .pyo'-Datei nicht schneller ausgeführt als beim Lesen aus einer '.py'-Datei. Das einzige, was bei '.pyc'- oder' .pyo'-Dateien schneller ist, ist die Geschwindigkeit, mit der sie geladen werden.

Der Vorteil des Ausführens einer .pyc-Datei besteht darin, dass Python vor dem Ausführen keinen zusätzlichen Aufwand für das Kompilieren verursachen muss. Da Python ohnehin vor dem Ausführen einer .py-Datei zu Bytecode kompilieren würde, sollte es ansonsten keine Leistungsverbesserung geben.

Wie viel Verbesserung können Sie durch die Verwendung kompilierter .pyc-Dateien erzielen? Das hängt davon ab, was das Skript macht. Bei einem sehr kurzen Skript, das einfach "Hello World" druckt, kann das Kompilieren einen großen Prozentsatz der gesamten Start- und Laufzeit ausmachen. Bei länger laufenden Skripten verringern sich jedoch die Kosten für das Kompilieren eines Skripts im Verhältnis zur Gesamtlaufzeit.

Das Skript, das Sie in der Befehlszeile benennen, wird niemals in einer .pyc-Datei gespeichert. Auf diese Weise werden nur Module gespeichert, die von diesem "Hauptskript" geladen wurden.

Bill Karwin
quelle
3
In vielen Fällen ist ein Unterschied schwer zu erkennen, aber ich habe eine bestimmte Python-Datei mit über 300.000 Zeilen. (Es handelt sich um eine Reihe von mathematischen Berechnungen, die von einem anderen Skript zum Testen generiert wurden.) Die Kompilierung dauert 37 Sekunden und die Ausführung nur 2 Sekunden.
Wojtow
54

Pluspunkte:

Erstens: milde, besiegbare Verschleierung.

Zweitens: Wenn die Kompilierung zu einer erheblich kleineren Datei führt, erhalten Sie schnellere Ladezeiten. Schön für das Web.

Drittens: Python kann den Kompilierungsschritt überspringen. Schneller bei Anfangslast. Schön für die CPU und das Web.

Viertens: Je mehr Sie kommentieren, desto kleiner ist die Datei .pycoder .pyoim Vergleich zur Quelle.py .

Fünftens: ein Endbenutzer mit nur einem .pycoder.pyo Datei in der Hand hat, zeigt Ihnen mit viel geringerer Wahrscheinlichkeit einen Fehler, der durch eine nicht rückgängig gemachte Änderung verursacht wurde, von der er vergessen hat, Ihnen davon zu erzählen.

Sechstens: Wenn Sie auf ein eingebettetes System abzielen, kann das Erhalten einer Datei mit kleinerer Größe zum Einbetten ein erhebliches Plus darstellen, und die Architektur ist stabil, sodass der unten beschriebene Nachteil nicht ins Spiel kommt.

Top Level Compilation

Es ist hilfreich zu wissen, dass Sie eine Python-Quelldatei der obersten Ebene folgendermaßen in eine .pycDatei kompilieren können:

python -m py_compile myscript.py

Dadurch werden Kommentare entfernt. Es lässt docstringsintakt. Wenn Sie das auch loswerden docstringsmöchten (Sie möchten vielleicht ernsthaft darüber nachdenken, warum Sie das tun), kompilieren Sie stattdessen auf diese Weise ...

python -OO -m py_compile myscript.py

... und Sie erhalten eine .pyoDatei anstelle einer .pycDatei; In Bezug auf die wesentliche Funktionalität des Codes gleichermaßen verteilbar, jedoch kleiner um die Größe des abgespeckten Codes docstrings(und für eine spätere Beschäftigung weniger leicht zu verstehen, wenn er anständig wardocstrings ). Aber siehe Nachteil drei unten.

Beachten Sie, dass Python .pydas Datum der Datei verwendet, falls vorhanden, um zu entscheiden, ob die .pyDatei im Gegensatz zur Datei .pycoder ausgeführt .pyowerden soll. Bearbeiten Sie also Ihre .py-Datei, und das .pycoder .pyoist veraltet, und alle Vorteile, die Sie erhalten haben, gehen verloren. Sie müssen es neu kompilieren, um die .pycoder die .pyoVorteile wieder zu erhalten, wie sie möglicherweise sind.

Nachteile:

Erstens: Es gibt ein "magisches Cookie" .pycund .pyoDateien, die die Systemarchitektur angeben, in der die Python-Datei kompiliert wurde. Wenn Sie eine dieser Dateien in eine Umgebung eines anderen Typs verteilen, wird sie beschädigt. Wenn Sie das .pycoder .pyoohne das zugeordnete .pyNeukompilieren verteilen oder touches das .pycoder ersetzt .pyo, kann der Endbenutzer es auch nicht reparieren.

Zweitens: Wenn docstringsdie Verwendung der -OOBefehlszeilenoption wie oben beschrieben übersprungen wird, kann niemand auf diese Informationen zugreifen, was die Verwendung des Codes erschweren (oder unmöglich machen) kann.

Drittens: Die -OOOption von Python implementiert auch einige Optimierungen gemäß der -OBefehlszeilenoption. Dies kann zu Betriebsänderungen führen. Bekannte Optimierungen sind:

  • sys.flags.optimize = 1
  • assert Anweisungen werden übersprungen
  • __debug__ = Falsch

Viertens: Wenn Sie Ihr Python-Skript absichtlich mit etwas in der Reihenfolge #!/usr/bin/pythonin der ersten Zeile ausführbar gemacht haben , wird dies in .pycund .pyoDateien entfernt und diese Funktionalität geht verloren.

Fünftens: etwas offensichtlich, aber wenn Sie Ihren Code kompilieren, kann nicht nur seine Verwendung beeinträchtigt werden, sondern das Potenzial für andere, aus Ihrer Arbeit zu lernen, wird häufig erheblich verringert.

Fyngyrz
quelle
10

Es gibt eine Leistungssteigerung beim Ausführen von kompiliertem Python. Wenn Sie jedoch eine .py-Datei als importiertes Modul ausführen, wird sie von Python kompiliert und gespeichert. Solange sich die .py-Datei nicht ändert, wird immer die kompilierte Version verwendet.

Bei jeder Interpeted-Sprache, wenn die Datei verwendet wird, sieht der Prozess ungefähr so ​​aus:
1. Die Datei wird vom Interpeter verarbeitet.
2. Datei wird kompiliert
3. Kompilierter Code wird ausgeführt.

Natürlich können Sie mit vorkompiliertem Code Schritt 2 eliminieren. Dies gilt für Python, PHP und andere.

Hier ist ein interessanter Blog-Beitrag, der die Unterschiede erklärt http://julipedia.blogspot.com/2004/07/compiled-vs-interpreted-languages.html
Und hier ist ein Eintrag, der den Python-Kompilierungsprozess erklärt http://effbot.org/zone /python-compile.htm

UnkwnTech
quelle
9

Wie bereits erwähnt, können Sie eine Leistungssteigerung erzielen, wenn Sie Ihren Python-Code in Bytecode kompilieren lassen. Dies wird normalerweise von Python selbst erledigt, nur für importierte Skripte.

Ein weiterer Grund, warum Sie Ihren Python-Code kompilieren möchten, könnte darin bestehen, Ihr geistiges Eigentum vor dem Kopieren und / oder Ändern zu schützen.

Weitere Informationen hierzu finden Sie in der Python-Dokumentation .

Simon B. Jensen
quelle
2
In Bezug auf den Schutz Ihres Codes hilft das Kompilieren nicht viel. Das Kompilieren verschleiert - aber jemand mit dem Wunsch wird Ihren Code trotzdem erhalten.
Josh Smeaton
1
@josh das ist immer möglich, wenn man auf den speicher zugreifen oder die anweisungen zur cpu sehen kann, mit genügend zeit und willen können sie ihre app neu erstellen.
UnkwnTech
5
Einverstanden, wie Unkwntech sagte, wird dies immer möglich sein, wenn die Person entschlossen genug ist. Aber ich bin überzeugt, dass es in den meisten Situationen ausreichen wird, in denen Sie normalerweise nur verhindern möchten, dass Leute Ihren Code "reparieren" ...
Simon B. Jensen
Sprachen, der Bytecode kompiliert werden , sind in der Regel gar nicht , dass schwer Reverse-Kompilierung , wenn Sie zusätzliche Schritte unternehmen , um sie zu verschleiern - lediglich allgemein Kompilieren nicht ausreichen wird.
EJoshuaS
7

Es gibt sicherlich einen Leistungsunterschied beim Ausführen eines kompilierten Skripts. Wenn Sie normale .pySkripte ausführen , kompiliert der Computer diese bei jeder Ausführung, was einige Zeit in Anspruch nimmt. Auf modernen Maschinen ist dies kaum wahrnehmbar, aber wenn das Skript wächst, kann es zu einem größeren Problem werden.

Matpie
quelle
7

Etwas, das nicht angesprochen wird, ist das Kompilieren von Quelle zu Quelle . Beispielsweise,nuitka übersetzt Python - Code zu C / C ++, und kompiliert es auf Binär - Code, der auf der CPU direkt ausgeführt wird , anstelle von Python - Bytecode , die auf der langsameren virtuellen Maschine ausgeführt wird .

Dies kann zu erheblichen Beschleunigungen führen, oder Sie können mit Python arbeiten, während Ihre Umgebung von C / C ++ - Code abhängt.

user258532
quelle
4

Wir verwenden kompilierten Code, um ihn an Benutzer zu verteilen, die keinen Zugriff auf den Quellcode haben. Grundsätzlich, um unerfahrene Programmierer davon abzuhalten, versehentlich etwas zu ändern oder Fehler zu beheben, ohne es uns mitzuteilen.

DrBwts
quelle
2

Ja, Leistung ist der Hauptgrund und, soweit ich weiß, der einzige Grund.

Wenn einige Ihrer Dateien nicht kompiliert werden, kann Python möglicherweise nicht in die .pyc-Datei schreiben, möglicherweise aufgrund der Verzeichnisberechtigungen oder Ähnlichem. Oder vielleicht werden die nicht kompilierten Dateien nie geladen ... (Skripte / Module werden erst kompiliert, wenn sie zum ersten Mal geladen werden)

David Z.
quelle
1

Anfänger gehen davon aus, dass Python aufgrund von .pyc-Dateien kompiliert wurde. Die .pyc-Datei ist der kompilierte Bytecode, der dann interpretiert wird. Wenn Sie also Ihren Python-Code zuvor ausgeführt haben und die .pyc-Datei zur Hand haben, wird sie beim zweiten Mal schneller ausgeführt, da der Bytecode nicht neu kompiliert werden muss

Compiler: Ein Compiler ist ein Code, der die Hochsprache in Maschinensprache übersetzt

Dolmetscher: Dolmetscher konvertieren die Hochsprache auch in maschinenlesbare binäre Äquivalente. Jedes Mal, wenn ein Interpreter einen High-Level-Sprachcode zur Ausführung erhält, konvertiert er den Code in einen Zwischencode, bevor er ihn in den Maschinencode konvertiert. Jeder Teil des Codes wird interpretiert und dann separat in einer Sequenz ausgeführt. In einem Teil des Codes wird ein Fehler gefunden, der die Interpretation des Codes stoppt, ohne den nächsten Satz der Codes zu übersetzen.

Quellen: http://www.toptal.com/python/why-are-there-so-many-pythons http://www.engineersgarage.com/contribution/difference-between-compiler-and-interpreter

Anfänger
quelle
9
Ihre Definition von "Compiler" ist falsch. Ein Compiler war noch nie unter, um zu Maschinencode zu kompilieren. Ein Compiler ist lediglich ein Übersetzer von einer Sprache in eine andere. Aus diesem Grund sagen wir, dass Python zu Bytecode "kompiliert", Coffeescript zu Javascript "kompiliert" und so weiter und so fort.
Ricky Stewart