Wie funktioniert die Python Runtime eigentlich?

26

Ich habe einige Probleme, das Konzept von a zu verstehen runtime library, insbesondere das von Python. Also habe ich ein Hallo-Welt-Python-Programm geschrieben und beabsichtige, es auszuführen, also schreibe ich python ./hello_world.py.

Welche Schritte passieren zwischen dem Drücken der Eingabetaste und dem Maschinencode, der aus meinem Python-Code generiert wurde, der auf meiner CPU ausgeführt wird? Und wie hängt das mit dem Python-Laufzeitsystem und / oder der Bibliothek zusammen?

hgiesel
quelle
Diese beiden Threads bieten einen guten Einblick in die Python-Laufzeit: Wird Python interpretiert oder kompiliert oder beides? & Wird Python interpretiert (wie Javascript oder PHP)? . Laufzeit und Laufzeitbibliothek sind nicht dasselbe. Abbildung auf die mir bekannte .NET-Welt - die Common Language Runtime (CLR) und die Framework- / Basisklassenbibliothek (FCL / BCL) sind nicht identisch.
RBT

Antworten:

33

So vielfältig sie auch sind, es gibt eine Handvoll gemeinsamer Konzepte, die alle seriösen, modernen Programmiersprachen gemeinsam haben. Zwei davon bilden den Kern der Antwort auf Ihre obigen Fragen.

Welche Schritte passieren zwischen dem Drücken der Eingabetaste und dem Maschinencode, der aus meinem Python-Code generiert wurde, der auf meiner CPU ausgeführt wird?

Der Code wird analysiert, analysiert und in einen Interpreter eingegeben. Hier geht es um ein sehr wichtiges Gebiet der Informatik, das als Compilertheorie bekannt ist . Ein Compiler ist ein Programm, das Code aus einer Sprache (Ihrem Quellcode) in eine andere Sprache übersetzt (in der Regel Maschinencode, obwohl es "Transpiler" gibt, die von einer höheren Sprache in eine andere übersetzen). Dies ist ein wirklich umfangreiches Thema, über das Sie jahrelang recherchieren könnten, aber hier ist die Basisversion:

Der Compiler beginnt mit einem Parser , einer Routine, die Ihren Quellcode liest und die Syntaxregeln der Sprache anwendet, um herauszufinden, ob es als gültiger Python-Code (in Ihrem Fall) Sinn macht. Wenn dies nicht der Fall ist, gibt der Parser einen Fehler aus und der Compiler wird beendet. Wenn dies jedoch der Fall ist, gibt der Parser einen sogenannten abstrakten Syntaxbaum, kurz AST, aus. Der AST ist eine Baumdatenstruktur, deren Knoten jeweils ein Element der Syntax enthalten. Wenn Sie beispielsweise sagen x = 5, könnten Sie einen BinaryExpressionKnoten mit einem operatorWert von =, einem LeftWert von ReferenceExpression(x)und einem RightWert von erhalten IntegerLiteralExpression(5). Ihr gesamtes Programm kann durch einen großen Baum wie diesen dargestellt werden.

Sobald der Parser einen AST erzeugt, ist die zweite Phase die semantische Analyse . Im Klartext bedeutet dies "herausfinden, was dieser AST bedeutet". Es überprüft den AST, um festzustellen, ob Sie etwas Illegales getan haben, obwohl es sich um eine gültige Analyse handelt (z. B. um den Versuch, eine 1-Argument-Funktion mit 3 Argumenten aufzurufen), und löst in diesem Fall Fehler aus. Andernfalls wird der AST analysiert und bearbeitet, um das Verständnis für eine Maschine zu vereinfachen.

Die dritte Phase ist die Codegenerierung. Sobald Sie einen vollständig analysierten, vereinfachten und gültigen AST haben, geben Sie ihn an den Generator weiter, der den AST durchläuft und Code in der Ausgabesprache erzeugt. Dies ist Ihr fertiges Produkt.

In Python wird eher ein Interpreter als ein Compiler verwendet. Ein Interpreter funktioniert genauso wie ein Compiler, mit dem Unterschied, dass er anstelle der Codegenerierung die Ausgabe im Arbeitsspeicher lädt und direkt auf Ihrem System ausführt. (Die genauen Details, wie dies geschieht, können je nach Sprache und Dolmetscher sehr unterschiedlich sein.)

Und wie hängt das mit dem Python-Laufzeitsystem und / oder der Bibliothek zusammen?

Mit Ausnahme der einfachsten Sprachen verfügen alle Sprachen über eine Reihe vordefinierter Funktionen, die für einen großen Prozentsatz der Benutzer wichtig sind und die für die Benutzer aus dem einen oder anderen Grund nur schwer selbst zu implementieren sind. Ihr Code kann diese Funktionen aufrufen, ohne dass Bibliotheken von Drittanbietern erforderlich sind. (Zum Beispiel in Python print, an das die Ausgabe gesendet wird stdout. Viel Glück beim Implementieren!) Diese Funktionsgruppe wird im Allgemeinen in einer gemeinsam genutzten Bibliothek gesammelt, in die der Code zur Laufzeit aufgerufen werden kann. Aus diesem Grund ist sie bekannt als Sprachlaufzeitbibliothek oder kurz "die Laufzeit".

Mason Wheeler
quelle
Also wird mein Code einem anderen Programm (dem Python-Laufzeitsystem) zugeführt, das all das ausführt und endet, wenn mein Code endet (und natürlich nach der Bereinigung)?
Hgiesel
@hgiesel Ich glaube, dass in Pythons Fall der Interpreter Teil der Laufzeit ist. Dies ist nicht für jede Sprache der Fall. natürlich, aber es ist ziemlich häufig unter interpretierten Sprachen.
Mason Wheeler
5

Die Standard-Python-Implementierung ist eine virtuelle Maschine mit Bytecode. Dies bedeutet, dass der Maschinencode (Opcodes aus dem Opcode-Satz Ihres Prozessors) nicht aus Ihrem Programm generiert wird. Die OP - Codes werden nur ausgewählt aus dem OP - Codes, die bereits in die virtuelle Maschine erstellt , während die VM den Bytecode interpretiert.

Wie Ihr Programm in Bytecode umgewandelt wird, ist eine etwas andere Frage, aber die kurze Antwort lautet "durch Kompilieren, genau wie bei jeder anderen abwärtsgerichteten Sprachübersetzung".

Kilian Foth
quelle