La función API Python C PyEval_EvalCode
le permite ejecutar el código Python compilado. Quiero ejecutar un bloque del código Python como si se estuviera ejecutando dentro del alcance de una función, de modo que tenga su propio diccionario de variables locales que no afecte el estado global.C Python: Ejecutando el código Python dentro de un contexto
Esto parece bastante fácil de hacer, ya PyEval_EvalCode
permite proporcionar un local y global diccionario:
PyObject* PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)
El problema me encuentro con que tiene que ver con la forma en Python busca los nombres de variables. Considere el siguiente código, que ejecuto con PyEval_EvalCode
:
myvar = 300
def func():
return myvar
func()
Este código simple en realidad genera un error, ya que Python es incapaz de encontrar la variable myvar
desde dentro func
. Aunque myvar
está en el diccionario local en el ámbito externo, Python no lo copia en el diccionario local en el ámbito interno. La razón para esto es la siguiente:
Cada vez que Python busca un nombre de variable, primero comprueba locals
, luego comprueba globals
, y finalmente comprueba builtins
. En , el alcance del módulo, locals
y globals
son el MISMO objeto de diccionario. Por lo tanto, la declaración x = 5
en el alcance del módulo colocará x
en el diccionario locals
, que también es el diccionario globals
. Ahora, una función definida en el alcance del módulo que necesita buscar x
no encontrará x
dentro de la función-scope locals
, porque Python no copia locals de alcance de módulo en locales de ámbito de función. Pero esto normalmente no es un problema, porque puede encontrar x
en globals
.
x = 5
def foo():
print(x) # This works because 'x' in globals() == True
Es sólo con anidados funciones, que Python parece copiar los locales de alcance exterior en los locales interior de alcance. (También parece hacerlo con pereza, sólo si son necesarios en el ámbito interno.)
def foo():
x = 5
def bar():
print(x) # Now 'x' in locals() == True
bar()
Así, el resultado de todo esto es que en la ejecución de código en ámbito de módulo, tienes que asegúrese de que su diccionario global y su diccionario local sean el MISMO objeto, de lo contrario las funciones del alcance del módulo no podrán acceder a las variables del ámbito del módulo.
Pero en mi caso, NO QUIERO que el diccionario global y el diccionario local sean iguales. Entonces necesito alguna forma de decirle al intérprete de Python que estoy ejecutando el código en el alcance de la función. Hay alguna manera de hacer esto? Miré el PyCompileFlags
, así como los argumentos adicionales al PyEval_EvalCodeEx
y no puedo encontrar ninguna forma de hacerlo.
@ Channel72 ver arriba. – ecatmur