C Python: Ausführen von Python-Code in einem Kontext
Die Python C-API-FunktionPyEval_EvalCode
Lassen Sie uns kompilierten Python-Code ausführen. Ich möchte einen Block Python-Code ausführenals würde es im Rahmen einer Funktion ausgeführt, so dass es ein eigenes Wörterbuch lokaler Variablen hat, die den globalen Zustand nicht beeinflussen.
Dies scheint einfach genug zu sein, daPyEval_EvalCode
Mit dieser Option können Sie ein globales und ein lokales Wörterbuch bereitstellen:
PyObject* PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)
Das Problem, auf das ich stoße, hat damit zu tun, wie Python Variablennamen sucht. Betrachten Sie den folgenden Code, mit dem ich ausführePyEval_EvalCode
:
myvar = 300
def func():
return myvar
func()
Dieser einfache Code löst tatsächlich einen Fehler aus, da Python die Variable nicht finden kannmyvar
von innenfunc
. Obwohlmyvar
befindet sich im lokalen Wörterbuch im äußeren Bereich, Python kopiert es nicht in das lokale Wörterbuch im inneren Bereich. Der Grund dafür ist wie folgt:
Wann immer Python einen Variablennamen nachschlägt, prüft es zuerstlocals
, dann prüft esglobals
und schließlich prüft esbuiltins
. BeimModulumfang, locals
undglobals
sind das gleiche Dictionary-Objekt. Also die Aussagex = 5
am Modulumfang wird platziertx
in derlocals
Wörterbuch, das auch das istglobals
Wörterbuch. Nun wird eine Funktion im Modulbereich definiert, die nachgeschlagen werden mussx
werde nicht findenx
innerhalb des Funktionsumfangslocals
, weil Python keine Module-Scope-Locals in Function-Scope-Locals kopiert. Aber das ist normalerweise kein Problem, weil es finden kannx
imglobals
.
x = 5
def foo():
print(x) # This works because 'x' in globals() == True
Es geht nur mitverschachtelt funktioniert, dass Python anscheinend Outer-Scope-Locals in Inner-Scope-Locals kopiert. (Es scheint auch so träge zu sein, nur wenn sie im inneren Bereich benötigt werden.)
def foo():
x = 5
def bar():
print(x) # Now 'x' in locals() == True
bar()
Das Ergebnis all dessen ist, dass beim Ausführen von Code umModulumfangMÜSSEN Sie sicherstellen, dass Ihr globales und lokales Wörterbuch das gleiche Objekt sind, da sonst Modulbereichsfunktionen nicht auf Modulbereichsvariablen zugreifen können.
In meinem Fall möchte ich jedoch nicht, dass das globale und das lokale Wörterbuch gleich sind. Ich muss dem Python-Interpreter also mitteilen, dass ich Code im Funktionsumfang ausführe. Gibt es eine Möglichkeit, dies zu tun? Ich schaute auf diePyCompileFlags
sowie die zusätzlichen Argumente zuPyEval_EvalCodeEx
und kann keinen Weg finden, dies zu tun.