2013-07-27 4 views
7

Wenn ich durch die Liste der Python built-in Funktionen schaue, habe ich Mühe, die Nützlichkeit der Methode compile zu verstehen. Alle Beispiele, die ich finden konnte, weisen auf eine einfache "Hallo-Welt" hin. Es macht Sinn was es tut, aber nicht wenn es zu verwenden.Was ist der Haupteinsatz von Python 'compile'?

Ist das die gleiche Methode, mit der Python die .pyc-Dateien generiert?

Kann dies verwendet werden, um etwas von der dynamischen Natur von Python zu entfernen, um die Leistung bestimmter Code-Blöcke zu verbessern? (Wohl wissend, dass ein Modul in C ist der Weg vorkompilierte Module zu gehen.)

Antwort

6

Von hier aus: What's the difference between eval, exec, and compile in Python?:

compile ist eine geringere Version von exec und eval. Es führt oder evaluiert Ihre Anweisungen oder Ausdrücke nicht, sondern gibt ein Code-Objekt zurück, das es tun kann. Die Modi sind wie folgt:

  1. compile(string, '', 'eval') den Code-Objekt zurückgibt, die ausgeführt worden wären Sie eval(string) getan hatte. Beachten Sie, dass Sie nicht Anweisungen in diesem Modus verwenden können; Nur ein (einzelner) Ausdruck ist gültig.
  2. compile(string, '', 'exec') gibt das Codeobjekt zurück, das ausgeführt worden wäre, wenn Sie exec(string) getan hätten. Sie können hier eine beliebige Anzahl von Anweisungen verwenden.
  3. compile(string, '', 'single') ist wie der exec Modus, aber es wird alles außer der ersten Anweisung ignorieren. Beachten Sie, dass eine if/else Anweisung mit ihren Ergebnissen als eine einzelne Anweisung betrachtet wird.

UPDATE:

Wenn Python kompilieren?

Im Allgemeinen kompilieren Sie Python, um die Leistung zu nutzen. Kompilierter Code hat eine viel schnellere Startzeit, da er nicht kompiliert werden muss, aber läuft nicht schneller.

Am bemerkenswertesten wäre, würden Sie compile verwenden, wenn Sie Code in Bytecode von Hand konvertieren möchten. Dies bringt eine weitere wichtige, aber relevante Frage zur Sprache warum dies tun?

Wie in dieser magnificent article verwiesen:

wenn Sie wollen exec verwenden und Sie planen, dass Code mehr als einmal ausgeführt wird, stellen Sie sicher, dass Sie es in Bytecode kompiliert und dann ausführen, die Bytecode nur und nur in einem neuen Wörterbuch als Namespace.

Von besonderer Bedeutung ist dies:

Nun, wie viel schneller ausgeführt wird Bytecode über Bytecode Erstellen und , dass die Ausführung?:

$ Python -mtimeit es 'code = "a = 2, b = 3, c = a * b"' 'exec Code' 10000 Schleifen, am besten von 3: 22,7 usec pro Schleife

$ python -mtime it -s 'code = kompilieren ("a = 2; b = 3; c = a * b",
"", "exec")' 'exec code' 1000000 Schleifen, best of 3: 0,765 usec pro Schleife

32 mal so schnell für einen sehr kurzen Code Beispiel. Es wird viel schlimmer desto mehr Code haben Sie. Warum ist das der Fall? Weil das Parsen von Python Code und das Konvertieren in Bytecode eine teure Operation ist, verglichen mit dem Auswerten des Bytecodes. Das betrifft natürlich auch execfile, die Bytecode-Caches nicht verwendet, wie sollte es. Es wird nicht magisch prüfen, ob es eine .pyc Datei gibt, wenn Sie den Pfad zu einer foo.py Datei übergeben.

+0

Dies ist, was ich als zu gesammelt haben, was es tut, aber es ist immer noch nicht klar, wann/warum es zu benutzen. Das einzige, was mir in den Sinn kommt, wäre eine schnelle Überprüfung, ob vor dem Aufruf von 'eval'/'exec' ein Syntaxfehler aufgetreten ist. –

+0

@AdamLewis, meine Entschuldigung. Aktualisiert. – jrd1

+1

Großes Update. Ich hatte die Vermutung, dass es darauf ausgerichtet war, nur dann wirklich nützlich zu sein, wenn man das eingebaute 'exec' verwendet. Danke, dass Sie sich die Zeit genommen haben, etwas über das Thema zu erfahren. –

2

Um die dynamische Natur Sache zu beantworten, nein, nicht wirklich. Das resultierende Codeobjekt wird weiterhin interpretiert. derselbe Bytecode läuft noch.

Die nützlichste/beeindruckendste Verwendung von compile() (und Code-Generierung), die ich gesehen habe, ist in Jinja2. Es generiert tatsächlich Python-Code aus Ihren Vorlagen und verwendet dann kompilieren, so dass es mit 'native' (== Interpreter) Geschwindigkeit läuft, wenn das sinnvoll ist.

https://github.com/mitsuhiko/jinja2/blob/master/jinja2/environment.py#L506

Im Gegensatz zu, sagen wir, django.template, die variable Lookups, etc in "User-Space" (wieder, sozusagen - Metapher irgendwie komisch ist).

https://github.com/django/django/blob/master/django/template/base.py#L752

+0

Ich habe Django und Jinja beide benutzt, aber noch nie so tief in das Template-System gegraben. Ich stimme zu, dass das eine gute Möglichkeit ist, die Vorlagen zu verarbeiten. Vielleicht ist das ein Teil des Grundes, warum ich Jinga als Templating-System in Django benutzt habe :) –

Verwandte Themen