Globals und Einheimische in python exec ()

Ich versuche, ein Stück Python-Code mit exec auszuführen.

my_code = """ class A(object): pass print 'locals: %s' % locals() print 'A: %s' % A class B(object): a_ref = A """ global_env = {} local_env = {} my_code_AST = compile(my_code, "My Code", "exec") exec(my_code_AST, global_env, local_env) print local_env 

Was zu der folgenden Ausgabe führt

 locals: {'A': <class 'A'>} A: <class 'A'> Traceback (most recent call last): File "python_test.py", line 16, in <module> exec(my_code_AST, global_env, local_env) File "My Code", line 8, in <module> File "My Code", line 9, in B NameError: name 'A' is not defined 

Allerdings, wenn ich den Code zu diesem ändern –

 my_code = """ class A(object): pass print 'locals: %s' % locals() print 'A: %s' % A class B(A): pass """ global_env = {} local_env = {} my_code_AST = compile(my_code, "My Code", "exec") exec(my_code_AST, global_env, local_env) print local_env 

Dann funktioniert es gut – geben die folgende Ausgabe –

 locals: {'A': <class 'A'>} A: <class 'A'> {'A': <class 'A'>, 'B': <class 'B'>} 

Klar ist A vorhanden und zugänglich – was geht im ersten Stück Code falsch? Ich benutze 2.6.5, Jubel,

Colin

* UPDATE 1 *

Wenn ich die Einheimischen () innerhalb der Klasse –

 my_code = """ class A(object): pass print 'locals: %s' % locals() print 'A: %s' % A class B(object): print locals() a_ref = A """ global_env = {} local_env = {} my_code_AST = compile(my_code, "My Code", "exec") exec(my_code_AST, global_env, local_env) print local_env 

Dann wird klar, dass die Einheimischen () nicht an beiden Orten gleich sind –

 locals: {'A': <class 'A'>} A: <class 'A'> {'__module__': '__builtin__'} Traceback (most recent call last): File "python_test.py", line 16, in <module> exec(my_code_AST, global_env, local_env) File "My Code", line 8, in <module> File "My Code", line 10, in B NameError: name 'A' is not defined 

Allerdings, wenn ich das mache, gibt es kein Problem –

 def f(): class A(object): pass class B(object): a_ref = A f() print 'Finished OK' 

* UPDATE 2 *

Ok, also die docs hier – http://docs.python.org/reference/executionmodel.html

'Eine Klassendefinition ist eine ausführbare Anweisung, die Namen verwenden und definieren kann. Diese Referenzen folgen den normalen Regeln für die Namensauflösung. Der Namespace der Klassendefinition wird zum Attributwörterbuch der Klasse. Die im Klassenbereich definierten Namen sind in Methoden nicht sichtbar. '

Es scheint mir, dass 'A' als freie Variable innerhalb der ausführbaren Anweisung zur Verfügung gestellt werden muss, die die Definition von B ist, und dies geschieht, wenn wir f () oben nennen, aber nicht, wenn wir exec () verwenden. Dies lässt sich mit den folgenden –

 my_code = """ class A(object): pass print 'locals in body: %s' % locals() print 'A: %s' % A def f(): print 'A in f: %s' % A f() class B(object): a_ref = A """ 

Welche Ausgänge

 locals in body: {'A': <class 'A'>} A: <class 'A'> Traceback (most recent call last): File "python_test.py", line 20, in <module> exec(my_code_AST, global_env, local_env) File "My Code", line 11, in <module> File "My Code", line 9, in f NameError: global name 'A' is not defined 

Also ich denke, die neue Frage ist – warum sind die Einheimischen nicht als freie Variablen in Funktionen und Klassendefinitionen ausgesetzt – es scheint wie ein hübsches Standard-Schließungsszenario.

4 Solutions collect form web for “Globals und Einheimische in python exec ()”

Nun, ich glaube, es ist entweder ein Implementierungsfehler oder eine undokumentierte Designentscheidung. Der Kern der Frage ist, dass eine namenbindende Operation im Modul-Bereich an eine globale Variable binden sollte. Die Art und Weise, wie es erreicht wird, ist, dass auf der Modul-Ebene, globals () IS-Einheimischen () (versuchen Sie das eine im Dolmetscher), so dass, wenn Sie irgendwelche Namensbindung, es ordnet es, wie üblich, die Einheimischen ( ) Wörterbuch, das auch die globals ist, also eine globale Variable erstellt wird.

Wenn du eine Variable siehst, schickst du zuerst deine aktuellen Einheimischen, und wenn der Name nicht gefunden wird, überprüft man rekursiv die Einheimischen, die Bereiche für den Variablennamen enthalten, bis du die Variable findest oder den Modulumfang erreichst. Wenn Sie das erreichen, überprüfen Sie die globals, die angeblich die Einheimischen des Modulbereichs sein sollen.

 >>> exec(compile("import sys\nprint sys._getframe().f_code.co_name", "blah", "exec"), {}, {}) <module> >>> exec("a = 1\nclass A(object):\n\tprint a\n", {}, {}) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 2, in <module> File "<string>", line 3, in A NameError: name 'a' is not defined >>> d = {} >>> exec("a = 1\nclass A(object):\n\tprint a\n", d,d) 1 

Dieses Verhalten ist, warum Vererbung gearbeitet (die Namens-Lookup verwendet Code-Objekt-Bereich Einheimischen (), die in der Tat hatte A in it).

Am Ende ist es ein hässlicher Hack in der CPython-Implementierung, Special-Casing-Globals Lookup. Es verursacht auch einige unsinnliche künstliche Situationen – zB:

 >>> def f(): ... global a ... a = 1 ... >>> f() >>> 'a' in locals() True 

Bitte beachten Sie, dass dies alles meine Schlussfolgerung ist, die auf dem Durcheinander mit dem Interpreter basiert, während Sie Abschnitt 4.1 (Benennen und Binden) der Pythonsprache lesen. Während dies nicht endgültig ist (ich habe die Quellen von CPython nicht geöffnet), bin ich ziemlich sicher, dass ich über das Verhalten richtig bin.

Nach dem print locals() und globals() finden Sie den Grund, warum exec "nicht definierte" Ausnahme globals() , und Sie können dies versuchen

 d = dict(locals(), **globals()) exec (code, d, d) 

Wenn Ihre Frage ist, wie man die exec Anweisung zu verhalten, wie die Datei Umfang, ich folgte einige Hinweise in der verknüpften Frage und Bug und bekam es funktioniert, indem Sie ein einziges Wörterbuch für Globals und Einheimischen. Anscheinend ist der Dateizugriff ein spezieller Fall, in dem lokale Deklarationen automatisch in den globalen Geltungsbereich gesetzt werden.

 exec code in dict() 
 my_code = """ class A(object): pass class B(object): a = A """ my_code_AST = compile(my_code, "My Code", "exec") extra_global = "hi" global_env = {} exec my_code_AST in global_env print "global_env.keys() =", global_env.keys() print "Ba =", global_env["B"].a 

Druckt

 global_env.keys() = ['__builtins__', 'A', 'B'] Ba = <class 'A'> 

Hawkett, sagst du,

Der Hauptgrund, warum ich solche Einheimischen verwenden wollte, war, das ganze Zeug in der Code-String zu definieren, ohne dass alle anderen Sachen, die Python in die globals setzt.

Mit exec, wenn deine globals nicht __builtins__ definiert haben, fügt exec ein item, __builtins__ zu deinen globals hinzu, also bekommst du A, B und __builtins__ . __builtins__ selbst ist ein großes Wörterbuch, aber es ist immer das gleiche Element zu löschen (solange du warte, bis dein Code fertig ist, es zu benutzen, bevor du es löschst!). Dokumentiert unter exec () hier

Die docs für eval unter eingebauten Funktionen sagen

Wenn das globals-Wörterbuch vorhanden ist und keine " builtins " fehlt, werden die aktuellen globals in globals kopiert, bevor der Ausdruck geparkt wird.

Aber eigentlich scheint es nur zu kopieren __builtins__ in.

(Und nb, was jeder andere sagte: entweder setzen globals und Einheimischen das gleiche oder sagen, exec my_code_AST in global_env ohne eine separate local_env.)

  • Pythonumfang [doppelte]
  • Warum können Funktionen in Python-Druckvariablen im Umschließungsbereich funktionieren, können sie aber nicht in der Zuordnung verwenden?
  • Warum ist eine Klassenvariable nicht im Listenverständnis definiert, sondern eine andere ist?
  • Python: Wie erfasse ich eine Variable, die in einem nicht globalen Ahnenumfang angegeben ist?
  • Python: Wie kann ich eval () im lokalen Gültigkeitsbereich einer Funktion ausführen?
  • Python überschreibt Variablen in verschachtelten Funktionen
  • Wie kann ich auf eine Klassenvariable in einem Initialisierer in Python zugreifen?
  • Mit einer Variablen in einem Versuch, Fang, endgültige Aussage, ohne es draußen zu erklären
  • Variable Bereiche in Python-Klassen
  • Wie kann man Variablen eines anderen Bereichs ändern?
  • Variabler Bereich (Python Newbie)
  • Python ist die beste Programmiersprache der Welt.