Was sind .pyc-Dateien, wenn Python interpretiert wird?

1084

Ich habe verstanden, dass Python eine interpretierte Sprache ist ...
Wenn ich jedoch meinen Python- Quellcode betrachte, sehe ich .pycDateien, die Windows als "Kompilierte Python-Dateien" identifiziert.

Wo kommen diese rein?

froadie
quelle
3
Eine Begründung finden Sie unter stackoverflow.com/questions/11433579/… . Mit einem Wort: Geschwindigkeit.
user7610
Bedeutet das, dass selbst Python genau wie Java das Wort "Einmal schreiben, überall ausführen" hat?
Mrak Vladar
2
@MrakVladar Sogar Java ist "Einmal schreiben, überall ausführen [dass Sie eine JVM haben]". Python ist nicht anders; Es wird "überall dort ausgeführt, wo Sie eine virtuelle Python-Maschine haben". Der große Unterschied besteht darin, dass die meisten Python-Implementierungen den Compiler und den Interpreter in einer ausführbaren Datei kombinieren, anstatt sie wie javaund zu trennen javac.
Chepper

Antworten:

660

Sie enthalten Bytecode , zu dem der Python-Interpreter die Quelle kompiliert. Dieser Code wird dann von Pythons virtueller Maschine ausgeführt.

In der Python-Dokumentation wird die Definition folgendermaßen erklärt:

Python ist eine interpretierte Sprache im Gegensatz zu einer kompilierten, obwohl die Unterscheidung aufgrund des Vorhandenseins des Bytecode-Compilers verschwommen sein kann. Dies bedeutet, dass Quelldateien direkt ausgeführt werden können, ohne explizit eine ausführbare Datei zu erstellen, die dann ausgeführt wird.

entspannen
quelle
10
Interessant, danke. Wird Python also als rein interpretierte Sprache betrachtet?
Froadie
194
@froadie: Eine Sprache wird nicht als solche "interpretiert" oder "kompiliert". Eine bestimmte Implementierung kann ein Interpreter oder ein Compiler (oder ein Hybrid- oder ein JIT-Compiler) sein.
Joachim Sauer
30
Ein Test von 'kompiliert': Wird er nach tatsächlichen Maschinenanweisungen kompiliert? Python-Bytecode sind keine Maschinenanweisungen und auch keine Java-JVM-Anweisungen. Daher wird keine dieser Sprachen durch diese Definition kompiliert. Aber beide "kompiliert" zu einem Zwischencode für "abstrakte Maschinen", und beide sind weitaus schneller als das Ausführen des Programms, indem sie den Quellcode mehr oder weniger direkt interpretieren (was BASIC der alten Schule tut).
Greggo
20
Um pedantisch zu sein, bedeutet "kompiliert" "übersetzt". Python wird dann zu einem Bytecode kompiliert . AFAIK, nur Bash wird wirklich interpretiert, alle anderen populären "interpretierten" Sprachen werden alle zu einem Bytecode kompiliert.
Bfontaine
13
Tatsächlich handelt es sich um Maschinenanweisungen, nur nicht um native Maschinenanweisungen für die physische CPU des Hosts. Deshalb nennen wir es eine VM? Wie Esperanto für Assemblersprache wirklich. Heutzutage haben wir sogar nativen Code für fiktive (aber immer noch emulierte) CPUs (Mojangs Bemühungen, die Kinder zu interessieren). Rexx wurde (oder könnte) wirklich interpretiert, und BAT und CMD (und DCL) werden interpretiert.
McKenzm
994

Ich habe verstanden, dass Python eine interpretierte Sprache ist ...

Dieses beliebte Mem ist falsch oder vielmehr auf einem Missverständnis der (natürlichen) Sprachniveaus aufgebaut: Ein ähnlicher Fehler wäre zu sagen: "Die Bibel ist ein gebundenes Buch". Lassen Sie mich dieses Gleichnis erklären ...

"Die Bibel" ist "ein Buch" im Sinne einer Klasse von (tatsächlichen, physischen Objekten, die als) Bücher identifiziert werden; Die Bücher, die als "Kopien der Bibel" bezeichnet werden, sollen etwas Grundlegendes gemeinsam haben (der Inhalt, obwohl auch diese in verschiedenen Sprachen mit unterschiedlichen akzeptablen Übersetzungen, Fußnotenebenen und anderen Anmerkungen vorliegen können) - diese Bücher sind es jedoch Es ist durchaus zulässig, sich in einer Vielzahl von Aspekten zu unterscheiden, die nicht als grundlegend angesehen werden - Art der Bindung, Farbe der Bindung, Schriftart (en), die beim Drucken verwendet werden, Abbildungen, breite Beschreibungsränder oder nicht, Anzahl und Art der eingebauten Lesezeichen , und so weiter und so fort.

Es ist durchaus möglich, dass ein typischer Druck der Bibel tatsächlich in gebundener Form vorliegt - schließlich handelt es sich um ein Buch, das normalerweise immer wieder gelesen, an mehreren Stellen mit Lesezeichen versehen und nach bestimmten Kapiteln und Versen gesucht werden soll usw. usw. und eine gute Hardcover-Bindung können dazu führen, dass eine bestimmte Kopie bei einer solchen Verwendung länger hält. Dies sind jedoch alltägliche (praktische) Probleme, anhand derer nicht festgestellt werden kann, ob ein bestimmtes tatsächliches Buchobjekt eine Kopie der Bibel ist oder nicht: Taschenbuchdrucke sind durchaus möglich!

In ähnlicher Weise ist Python "eine Sprache" im Sinne der Definition einer Klasse von Sprachimplementierungen , die alle in einigen grundlegenden Aspekten ähnlich sein müssen (Syntax, die meisten Semantiken mit Ausnahme der Teile derjenigen, in denen sie sich ausdrücklich unterscheiden dürfen), aber vollständig zulässig sind Sie unterscheiden sich in nahezu jedem "Implementierungs" -Detail - einschließlich des Umgangs mit den angegebenen Quelldateien, der Kompilierung der Quellen in Formulare niedrigerer Ebene (und, falls ja, des Formulars) und der Speicherung solcher Formulare kompilierte Formulare (auf Festplatte oder anderswo), wie sie diese Formulare ausführen, und so weiter.

Die klassische Implementierung, CPython, wird oft nur kurz "Python" genannt - aber es ist nur eine von mehreren Implementierungen in Produktionsqualität, neben Microsoft IronPython (das zu CLR-Codes kompiliert wird, dh ".NET"), Jython (das zu JVM-Codes kompiliert wird), PyPy (das in Python selbst geschrieben ist und zu einer Vielzahl von "Back-End" -Formen kompiliert werden kann, einschließlich "Just-in-Time" -generierter Maschinensprache). Sie sind alle Python (== "Implementierungen der Python-Sprache"), genau wie viele oberflächlich unterschiedliche Buchobjekte Bibeln sein können (== "Kopien der Bibel").

Wenn Sie sich speziell für CPython interessieren: Es kompiliert die Quelldateien in eine Python-spezifische Form auf niedrigerer Ebene (bekannt als "Bytecode"), und zwar automatisch bei Bedarf (wenn keine Bytecodedatei vorhanden ist, die einer Quelldatei entspricht, oder Die Bytecode-Datei ist älter als die Quelle oder von einer anderen Python-Version kompiliert. Normalerweise werden die Bytecode-Dateien auf der Festplatte gespeichert (um ein erneutes Kompilieren in Zukunft zu vermeiden). OTOH IronPython kompiliert normalerweise zu CLR-Codes (sie werden auf der Festplatte gespeichert oder nicht) und Jython zu JVM-Codes (sie werden auf der Festplatte gespeichert oder nicht - es wird die .classErweiterung verwendet, wenn sie gespeichert werden ).

Diese Formulare auf niedrigerer Ebene werden dann von geeigneten "virtuellen Maschinen" ausgeführt, die auch als "Interpreter" bezeichnet werden - der CPython-VM, der .NET-Laufzeit, der Java-VM (auch bekannt als JVM).

In diesem Sinne (was machen typische Implementierungen) ist Python genau dann eine "interpretierte Sprache", wenn C # und Java es sind: Alle haben eine typische Implementierungsstrategie, zuerst Bytecode zu erzeugen und ihn dann über eine VM / einen Interpreter auszuführen .

Wahrscheinlicher ist der Fokus darauf, wie "schwer", langsam und hochzerreißend der Kompilierungsprozess ist. CPython ist so konzipiert, dass es so schnell wie möglich, so leicht wie möglich und mit so wenig Zeremonie wie möglich kompiliert wird. Der Compiler führt nur sehr wenige Fehlerprüfungen und -optimierungen durch, sodass er schnell und in geringem Speicher ausgeführt werden kann, was es wiederum ermöglicht Sie können bei Bedarf automatisch und transparent ausgeführt werden, ohne dass der Benutzer sich darüber im Klaren sein muss, dass die meiste Zeit eine Kompilierung stattfindet. Java und C # akzeptieren normalerweise mehr Arbeit während der Kompilierung (und führen daher keine automatische Kompilierung durch), um Fehler gründlicher zu überprüfen und mehr Optimierungen durchzuführen. Es ist ein Kontinuum von Graustufen, keine schwarze oder weiße Situation,

Alex Martelli
quelle
2
Schöne Antwort. Nur eine kleine Korrektur zum letzten Absatz: Python wurde entwickelt, um so schnell wie möglich zu kompilieren (usw.). Diesmal ist es wirklich die Sprache, mit ihrem Mangel an statischem Typsystem und Zeug. Wenn Leute über "interpretierte" Sprachen sprechen, meinen sie normalerweise "dynamische" Sprachen.
Elazar
1
@Elazar Tatsächlich schaffen es andere Implementierungen von Python wie PyPy, deren Kompilierung nicht eilig ist, die gründlichere Analyse durchzuführen, die aufgrund der fehlenden statischen Typisierung erforderlich ist, und erstellen eine Just-in-Time-Kompilierung des Maschinencodes (wodurch die Geschwindigkeit erhöht wird) lang laufende Programme um ein Vielfaches).
Alex Martelli
Wo passt Cython hierher? Würden Sie es als eine andere Sprache betrachten oder ist es eine Python-Implementierung? Ist dieses Mem von "interpretiert" vs kompiliert vielleicht nur eine terminologische Verwirrung, weil Pythons VM oft als "Interpreter" bezeichnet wird? Es wäre genauso gültig, die JVM- oder die .NET-Laufzeitinterpreter aufzurufen. Beide interpretieren Bytecode meistens in JIT-Maschinencode (mit einigen Ausnahmen bei der Caching-Optimierung)
Davos,
181

Es gibt keine interpretierte Sprache. Ob ein Interpreter oder ein Compiler verwendet wird, ist nur ein Merkmal der Implementierung und hat absolut nichts mit der Sprache zu tun.

Jede Sprache kann entweder von einem Interpreter oder einem Compiler implementiert werden. Die überwiegende Mehrheit der Sprachen verfügt über mindestens eine Implementierung für jeden Typ. (Zum Beispiel gibt es Interpreter für C und C ++ und Compiler für JavaScript, PHP, Perl, Python und Ruby.) Außerdem kombinieren die meisten modernen Sprachimplementierungen tatsächlich sowohl einen Interpreter als auch einen Compiler (oder sogar mehrere Compiler).

Eine Sprache ist nur ein Satz abstrakter mathematischer Regeln. Ein Dolmetscher ist eine von mehreren konkreten Implementierungsstrategien für eine Sprache. Diese beiden leben auf völlig unterschiedlichen Abstraktionsebenen. Wenn Englisch eine getippte Sprache wäre, wäre der Begriff "interpretierte Sprache" ein Tippfehler. Die Aussage "Python ist eine interpretierte Sprache" ist nicht nur falsch (weil falsch zu sein bedeuten würde, dass die Aussage sogar Sinn macht, auch wenn sie falsch ist), sie macht einfach keinen Sinn , weil eine Sprache niemals als definiert werden kann "interpretiert."

Wenn Sie sich insbesondere die derzeit vorhandenen Python-Implementierungen ansehen, sind dies die Implementierungsstrategien, die sie verwenden:

  • IronPython: Kompiliert zu DLR-Bäumen, die das DLR dann zu CIL-Bytecode kompiliert. Was mit dem CIL-Bytecode passiert, hängt davon ab, auf welcher CLI-VES Sie ausgeführt werden. Microsoft .NET, GNU Portable.NET und Novell Mono kompilieren ihn jedoch schließlich zu nativem Computercode.
  • Jython: Interpretiert den Python-Quellcode, bis er die Hot-Code-Pfade identifiziert, die er dann zu JVML-Bytecode kompiliert. Was mit dem JVML-Bytecode passiert, hängt davon ab, auf welcher JVM Sie ausgeführt werden. Maxine kompiliert es direkt zu nicht optimiertem nativem Code, bis es die Hot-Code-Pfade identifiziert, die es dann zu optimiertem nativem Code neu kompiliert. HotSpot interpretiert zuerst den JVML-Bytecode und kompiliert schließlich die Hotcode-Pfade zu optimiertem Maschinencode.
  • PyPy: Kompiliert zu PyPy-Bytecode, der dann von der PyPy-VM interpretiert wird, bis die Hot-Code-Pfade identifiziert werden, die dann in nativen Code, JVML-Bytecode oder CIL-Bytecode kompiliert werden, je nachdem, auf welcher Plattform Sie ausgeführt werden.
  • CPython: Kompiliert zu CPython-Bytecode, den es dann interpretiert.
  • Stapelloses Python: Kompiliert zu CPython-Bytecode, den es dann interpretiert.
  • Unladen Swallow: Kompiliert zu CPython-Bytecode, den es dann interpretiert, bis es die Hot-Code-Pfade identifiziert, die es dann zu LLVM IR kompiliert, die der LLVM-Compiler dann zu nativem Maschinencode kompiliert.
  • Cython: Kompiliert Python-Code zu portablem C-Code, der dann mit einem Standard-C-Compiler kompiliert wird
  • Nuitka: Kompiliert Python-Code in maschinenabhängigen C ++ - Code, der dann mit einem Standard-C-Compiler kompiliert wird

Möglicherweise stellen Sie fest, dass jede einzelne Implementierung in dieser Liste (und einige andere, die ich nicht erwähnt habe, wie Tinypy, Shedskin oder Psyco) einen Compiler hat. Soweit ich weiß, gibt es derzeit keine rein interpretierte Python-Implementierung, es ist keine solche Implementierung geplant und es hat noch nie eine solche Implementierung gegeben.

Der Begriff "interpretierte Sprache" ist nicht nur nicht sinnvoll, auch wenn Sie ihn als "Sprache mit interpretierter Implementierung" interpretieren, er ist eindeutig nicht wahr. Wer dir das gesagt hat, weiß offensichtlich nicht, wovon er spricht.

Insbesondere handelt es sich bei den .pycangezeigten Dateien um zwischengespeicherte Bytecode-Dateien, die von CPython, Stackless Python oder Unladen Swallow erstellt wurden.

Jörg W Mittag
quelle
5
Old-School-Grundlagen wie MSBASIC hatten keine Zwischenform. Das Programm wurde direkt aus dem Quellformular interpretiert (oder aus der Nähe der Quelle, einer Form, in der Schlüsselwörter durch 1-Byte-Token und Zeilennummern durch 2-Byte-Binär-Ints dargestellt wurden, der Rest war jedoch nur ASCII). Tatsächlich würde ein "goto" unterschiedlich lange dauern, je nachdem, wie viele Quellzeilen er durchsuchen musste, um nach dem passenden Ziel zu suchen. Ausdrücke wie a * b-2 * cos (x) wurden bei jeder Ausführung effektiv neu analysiert.
Greggo
4
@greggo: Und wenn Sie noch mehr Old-School wollen, war die Originalversion von BASIC ein nativer Code-Compiler. Dies sollte beweisen, wie lächerlich die Vorstellung einer "kompilierten" oder "interpretierten" Sprache ist.
Jörg W Mittag
Vielen Dank, dass Sie erklärt haben, wie sich die verschiedenen Python-Compiler / Interpreter verhalten. Ich frage mich, ob es gute Python-Compiler gibt, die noch effizientes C oder JavaScript generieren. Es scheint sehr machbar zu sein, vielleicht nicht für den Massenkonsum, aber zumindest für eine vernünftige Teilmenge von Python. Ich frage mich auch, was Cython ist.
personal_cloud
Cython wurde in SciPy 2009 erwähnt, aber ich kann Ihnen verzeihen, dass Sie 2010 nichts davon gewusst haben (hier lerne ich erst 2017 davon). Trotzdem sollten wir ein JavaScript-Beispiel finden ... Jython macht für mich keinen Sinn (war Java bis 2009 nicht schon tot? Nun hmm, vielleicht auch nicht ... C ++ - Boost war damals nicht so gut)
personal_cloud
1
@personal_cloud: Ich folge deinem Kommentar nicht ganz. Ja, natürlich weiß ich über Cython Bescheid, aber was hat das mit irgendetwas zu tun? Es ist keine Implementierung von Python, es ist eine völlig andere Sprache. Außerdem ist es nicht schwer, ein JavaScript-Beispiel zu finden. Tatsächlich verfügen alle derzeit vorhandenen JavaScript-Mainstream-Implementierungen über Compiler. Schließlich ist Jython eine Implementierung von Python, genau wie jede andere Implementierung von Python. Und es ist eine Implementierung einer Sprache auf der Java-Plattform, genau wie jede andere Sprachimplementierung auf der Java-Plattform.
Jörg W Mittag
61

Diese werden vom Python-Interpreter beim .pyImportieren einer Datei erstellt und enthalten den "kompilierten Bytecode" des importierten Moduls / Programms. Die Idee ist, dass die "Übersetzung" vom Quellcode zum Bytecode (die nur einmal durchgeführt werden muss) kann bei nachfolgenden imports übersprungen werden, wenn die Datei .pycneuer als die entsprechende .pyDatei ist, wodurch der Start etwas beschleunigt wird. Aber es wird immer noch interpretiert.

Tim Pietzcker
quelle
10
Wahr. Außer, dass viele Python-Kernbibliotheken in C geschrieben sind. Teile von Python werden also interpretiert, Teile werden in C ausgeführt. Sie können dasselbe mit Ihren eigenen leistungsempfindlichen Codebits tun.
Bwawok
44

Um das Laden von Modulen zu beschleunigen, speichert Python den kompilierten Inhalt von Modulen in .pyc zwischen.

CPython kompiliert seinen Quellcode in "Bytecode" und speichert diesen Bytecode aus Leistungsgründen im Dateisystem zwischen, wenn sich an der Quelldatei Änderungen ergeben. Dies beschleunigt das Laden von Python-Modulen erheblich, da die Kompilierungsphase umgangen werden kann. Wenn Ihre Quelldatei foo.py ist, speichert CPython den Bytecode in einer foo.pyc-Datei direkt neben der Quelle zwischen.

In Python3 wird die Importmaschinerie von Python erweitert, um Bytecode-Cache-Dateien in einem einzigen Verzeichnis in jedem Python-Paketverzeichnis zu schreiben und zu suchen. Dieses Verzeichnis heißt __pycache__.

Hier ist ein Flussdiagramm, das beschreibt, wie Module geladen werden:

Geben Sie hier die Bildbeschreibung ein

Für mehr Informationen:

ref: PEP3147
ref: "Kompilierte" Python-Dateien

hxysayhi
quelle
38

DAS IST FÜR ANFÄNGER,

Python kompiliert Ihr Skript automatisch zu kompiliertem Code, dem sogenannten Bytecode, bevor es ausgeführt wird.

Das Ausführen eines Skripts wird nicht als Import betrachtet und es wird kein .pyc erstellt.

Zum Beispiel, wenn Sie eine Skriptdatei haben abc.py , dass die Einfuhren ein anderes Modul xyz.py , wenn Sie laufen abc.py , xyz.pyc erstellt werden , da xyz importiert wird, aber keine abc.pyc Datei wird erstellt , da abc. py wird nicht importiert.

Wenn Sie eine .pyc-Datei für ein Modul erstellen müssen, das nicht importiert wird, können Sie die Module py_compileund verwenden compileall.

Das py_compileModul kann jedes Modul manuell kompilieren. Eine Möglichkeit besteht darin, die py_compile.compileFunktion in diesem Modul interaktiv zu verwenden:

>>> import py_compile
>>> py_compile.compile('abc.py')

Dadurch wird die .pyc-Datei an dieselbe Stelle wie abc.py geschrieben (Sie können dies mit dem optionalen Parameter überschreiben cfile).

Mit dem Modul compileall können Sie auch automatisch alle Dateien in einem Verzeichnis oder in Verzeichnissen kompilieren.

python -m compileall

Wenn der Verzeichnisname (in diesem Beispiel das aktuelle Verzeichnis) weggelassen wird, kompiliert das Modul alles, was auf gefunden wurde sys.path

MAX
quelle
6
und was ist der Vorteil des Kompilierens, um die abc.py zu erhalten?
Saher Ahwal
@ SaherAhwal Ein Vorteil, den ich mir vorstellen kann, ist die Syntaxprüfung.
Yi Bao
20

Python (zumindest die am häufigsten verwendete Implementierung) folgt einem Muster, bei dem die ursprüngliche Quelle zu Bytecodes kompiliert und anschließend die Bytecodes auf einer virtuellen Maschine interpretiert werden. Dies bedeutet (wiederum die häufigste Implementierung), dass es sich weder um einen reinen Interpreter noch um einen reinen Compiler handelt.

Die andere Seite davon ist jedoch, dass der Kompilierungsprozess größtenteils verborgen ist - die .pyc-Dateien werden im Grunde genommen wie ein Cache behandelt; Sie beschleunigen die Dinge, aber normalerweise müssen Sie sich ihrer überhaupt nicht bewusst sein. Es macht sie automatisch ungültig und lädt sie neu (kompiliert den Quellcode neu), falls erforderlich, basierend auf den Zeit- / Datumsstempeln der Datei.

Das einzige Mal, dass ich ein Problem damit gesehen habe, war, als eine kompilierte Bytecode-Datei irgendwie einen Zeitstempel in die Zukunft bekam, was bedeutete, dass sie immer neuer aussah als die Quelldatei. Da es neuer aussah, wurde die Quelldatei nie neu kompiliert. Unabhängig davon, welche Änderungen Sie vorgenommen haben, wurden sie ignoriert ...

Jerry Sarg
quelle
12

Die * .py-Datei von Python ist nur eine Textdatei, in die Sie einige Codezeilen schreiben. Wenn Sie versuchen, diese Datei mit "python filename.py" auszuführen

Dieser Befehl ruft Python Virtual Machine auf. Python Virtual Machine besteht aus zwei Komponenten: "Compiler" und "Interpreter". Der Interpreter kann den Text in der * .py-Datei nicht direkt lesen, daher wird dieser Text zuerst in einen Bytecode konvertiert, der auf die PVM abzielt (nicht Hardware, sondern PVM) . PVM führt diesen Bytecode aus. * .pyc-Datei wird ebenfalls generiert, wenn sie ausgeführt wird und Ihr Importvorgang für Dateien in der Shell oder in einer anderen Datei ausgeführt wird.

Wenn diese * .pyc-Datei bereits generiert wurde, lädt das System beim nächsten Ausführen / Ausführen Ihrer * .py-Datei direkt Ihre * .pyc-Datei, die nicht kompiliert werden muss (dies erspart Ihnen einige Maschinenzyklen des Prozessors).

Sobald die * .pyc-Datei generiert wurde, ist die * .py-Datei nicht mehr erforderlich, es sei denn, Sie bearbeiten sie.

Vishal Mopari
quelle
7

Python-Code durchläuft zwei Stufen. Der erste Schritt kompiliert den Code in .pyc-Dateien, die eigentlich ein Bytecode sind. Anschließend wird diese .pyc-Datei (Bytecode) mit dem CPython-Interpreter interpretiert. Bitte beziehen Sie sich auf diesen Link. Hier wird der Prozess der Codekompilierung und -ausführung in einfachen Worten erklärt.

Tango
quelle