it-swarm.com.de

Warum braucht Python keinen Compiler?

Ich frage mich nur (jetzt, wo ich mit C++ angefangen habe, das einen Compiler benötigt), warum Python benötigt keinen Compiler?

Ich gebe einfach den Code ein, speichere ihn als Exec und führe ihn aus. In C++ muss ich Builds und all das andere lustige Zeug machen.

29
Billjk

Python hat einen Compiler! Sie bemerken es einfach nicht, weil es automatisch ausgeführt wird. Sie können jedoch feststellen, dass es vorhanden ist: Sehen Sie sich die Dateien .pyc (Oder .pyo An, wenn Sie den Optimierer aktiviert haben) an, die für Module generiert werden, die Sie import.

Außerdem wird es nicht mit dem Code des nativen Computers kompiliert. Stattdessen wird ein Bytecode kompiliert, der von einer virtuellen Maschine verwendet wird. Die virtuelle Maschine ist selbst ein kompiliertes Programm. Dies ist sehr ähnlich wie Java funktioniert; so ähnlich, dass es tatsächlich eine Python Variante ( Jython ) gibt) Kompiliert mit dem Bytecode von Java Virtual Machine! Es gibt auch IronPython , das mit der CLR von Microsoft kompiliert wird (von .NET verwendet). (Das normale Python Bytecode-Compiler wird manchmal als CPython bezeichnet, um ihn von diesen Alternativen zu unterscheiden.)

C++ muss seinen Kompilierungsprozess verfügbar machen, da die Sprache selbst unvollständig ist. Es gibt weder alles an, was der Linker wissen muss, um Ihr Programm zu erstellen, noch kann er Kompilierungsoptionen portabel angeben (bei einigen Compilern können Sie #pragma verwenden, aber das ist kein Standard). Sie müssen also den Rest der Arbeit mit Makefiles und möglicherweise Auto Hell (Autoconf/Automake/Libtool) erledigen. Dies ist wirklich nur ein Überbleibsel von C. Und C hat es so gemacht, weil es den Compiler einfach gemacht hat, was ein Hauptgrund dafür ist, dass er so beliebt ist (jeder konnte in den 80ern einen einfachen C-Compiler herausbringen).


Einige Dinge, die sich auf den Betrieb des Compilers oder Linkers auswirken können, jedoch nicht in der Syntax von C oder C++ angegeben sind:

  • abhängigkeitsauflösung
  • anforderungen an die externe Bibliothek (einschließlich Abhängigkeitsreihenfolge)
  • optimierungsstufe
  • warneinstellungen
  • sprachspezifikationsversion
  • linker-Mappings (welcher Abschnitt geht wohin im endgültigen Programm)
  • zielarchitektur

Einige davon können erkannt, aber nicht angegeben werden. z.B. Ich kann erkennen, welches C++ mit __cplusplus Verwendet wird, aber ich kann nicht angeben, dass C++ 98 für meinen Code im Code selbst verwendet wird. Ich muss es als Flag an den Compiler im Makefile übergeben oder eine Einstellung in einem Dialog vornehmen.

Während Sie vielleicht denken, dass im Compiler ein "Abhängigkeitsauflösungssystem" vorhanden ist, das automatisch Abhängigkeitsdatensätze generiert, geben diese Datensätze nur an, welche Header-Dateien eine bestimmte Quelldatei verwendet. Sie können nicht angeben, welche zusätzlichen Quellcodemodule für die Verknüpfung mit einem ausführbaren Programm erforderlich sind, da es in C oder C++ keine Standardmethode gibt, um anzugeben, dass eine bestimmte Headerdatei die Schnittstellendefinition für ein anderes Quellcodemodul ist und nicht nur eine Reihe von Zeilen, die an mehreren Stellen angezeigt werden sollen, damit Sie sich nicht wiederholen. Es gibt Traditionen in Dateinamenskonventionen, aber diese sind dem Compiler und Linker nicht bekannt oder werden nicht durchgesetzt.

Einige davon können mit #pragma Eingestellt werden, aber dies ist kein Standard, und ich habe vom Standard gesprochen. All diese Dinge könnten durch einen Standard spezifiziert werden, waren jedoch nicht im Interesse der Abwärtskompatibilität. Die vorherrschende Weisheit ist, dass Makefiles und IDEs nicht kaputt sind, also reparieren Sie sie nicht.

Python behandelt dies alles in der Sprache. Beispielsweise gibt import eine explizite Modulabhängigkeit an, impliziert den Abhängigkeitsbaum und Module werden nicht in Header- und Quelldateien (d. H. Schnittstelle und Implementierung) aufgeteilt.

68
Mike DeSimone

Python ist eine interpretierte Sprache. Dies bedeutet, dass sich auf Ihrem Computer eine Software befindet, die den Code Python] liest und die "Anweisungen" an die Maschine sendet. Der Wikipedia-Artikel über interpretierte Sprachen könnte von sein Interesse.

Wenn eine Sprache wie C++ (eine kompilierte Sprache) kompiliert wird, bedeutet dies, dass sie in Maschinencode konvertiert wird, um bei der Ausführung direkt von der Hardware gelesen zu werden. Der Wikipedia-Artikel über kompilierte Sprachen könnte einen interessanten Kontrast bieten.

7
Zenon

Nicht alle kompilierten Sprachen verfügen über einen Zyklus zum Bearbeiten, Kompilieren und Ausführen von Links.

Was Sie antreffen, ist eine Funktion/Einschränkung von C++ (oder zumindest C++ - Implementierungen).

Um etwas zu tun, müssen Sie Ihren Code in Dateien speichern und ein monolithisches Bild durch einen Prozess namens Verknüpfen erstellen.

Insbesondere ist es dieser monolithische Verknüpfungsprozess, der mit der Unterscheidung zwischen Kompilieren und Interpretieren verwechselt wird.

Einige Sprachen erledigen all diese Dinge viel dynamischer, indem sie den ungeschickten monolithischen Verknüpfungsschritt eliminieren und nicht das Kompilieren in Maschinencode. Die Quelle wird weiterhin in Objektdateien kompiliert, diese werden jedoch in ein Laufzeitabbild geladen und nicht in eine monolithische ausführbare Datei verknüpft.

Sie sagen "Dieses Modul neu laden" und es lädt die Quelle und interpretiert sie oder kompiliert sie, abhängig von einem Modusschalter.

Die Linux-Kernel-Programmierung hat einige dieser Eigenschaften, obwohl Sie in C arbeiten. Sie können ein Modul neu kompilieren und es laden und entladen. Natürlich wissen Sie immer noch, dass Sie eine ausführbare Sache produzieren, und sie wird von einem komplexen Build-System mit noch einigen manuellen Schritten verwaltet. Tatsache ist jedoch, dass Sie am Ende nur dieses kleine Modul entladen und neu laden können und nicht den gesamten Kernel neu starten müssen.

Einige Sprachen haben eine noch feinkörnigere Modularisierung als diese, und das Erstellen und Laden erfolgt innerhalb ihrer Laufzeit, sodass es nahtloser ist.

5
Kaz

was für eine Ablenkung von der ursprünglichen Frage ... Ein Punkt, der nicht erwähnt wird, ist, dass die Quelle eines python Programms das ist, was Sie verwenden und verteilen, aus Benutzersicht das Programm IS. Wir neigen dazu, Dinge in Kategorien zu vereinfachen, die nicht genau definiert sind.

Kompilierte Programme werden normalerweise als eigenständige Dateien mit Maschinencode betrachtet. (Zugegebenermaßen häufig mit Links zu dynamischen Linkbibliotheken, die bestimmten Betriebssystemen zugeordnet sind). Dies sagte ... es gibt Variationen der meisten Programmiersprachen, die als kompiliert oder interpretiert beschrieben werden könnten.

Python benötigt keinen Compiler, da es auf einer Anwendung (Interpreter genannt) basiert, die den Code kompiliert und ausführt, ohne den erstellten Maschinencode in einer Form zu speichern, auf die Sie problemlos zugreifen oder die Sie verteilen können.

2

Alle Programmiersprachen erfordern die Übersetzung von menschlichen Konzepten in einen Zielmaschinencode. Auch die Assemblersprache muss in Maschinencode übersetzt werden. Diese Übersetzung erfolgt normalerweise in folgenden Phasen:

Phase 1: Analyse und Übersetzung (Parsing) in einen Zwischencode. Phase 2: Übersetzung des Zwischencodes in den Zielmaschinencode mit Platzhaltern für externe Referenzen. Phase 3: Auflösung der externen Referenzen und Verpackung in ein maschinenausführbares Programm.

Diese Übersetzung wird häufig als Vorkompilierung und "Just in Time" (JIT) oder Laufzeitkompilierung bezeichnet.

Sprachen wie C, C++, COBOL, Fortran, Pascal (nicht alle) und Assembly sind vorkompilierte Sprachen, die direkt vom Betriebssystem ausgeführt werden können, ohne dass ein Interpreter erforderlich ist.

Sprachen wie Java, BASIC, C # und Python werden interpretiert. Sie alle verwenden den in Phase 1 erstellten Zwischencode, unterscheiden sich jedoch manchmal darin, wie sie ihn in Maschinencode übersetzen. Die einfachsten Formulare verwenden diesen Zwischencode zum Ausführen von Maschinencoderoutinen, die die erwartete Arbeit erledigen. Andere kompilieren den Zwischencode bis zum Maschinencode und führen die externe Abhängigkeitsbehebung zur Laufzeit durch. Nach dem Kompilieren kann er sofort ausgeführt werden. Außerdem wird der Maschinencode in einem Cache gespeichert von zuvor kompiliertem wiederverwendbarem Maschinencode, der später wiederverwendet werden kann, wenn die Funktion später erneut benötigt wird. Wenn eine Funktion bereits zwischengespeichert wurde, muss der Interpreter sie nicht erneut kompilieren.

Die meisten modernen Hochsprachen fallen in die Kategorie der interpretierten (mit JIT). Es sind hauptsächlich die älteren Sprachen wie C & C++, die vorkompiliert werden.

1
Mark Baker