Функция API Python C PyEval_EvalCode
позволяет выполнять скомпилированный код Python. Я хочу выполнить блок кода Python , как если бы он выполнялся в рамках функции, поэтому он имеет свой собственный словарь локальных переменных, которые не влияют на глобальное состояние.
Это кажется достаточно простым, поскольку PyEval_EvalCode
позволяет вам предоставить глобальный и локальный словарь:
PyObject* PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)
Проблема, с которой я сталкиваюсь, связана с тем, как Python ищет имена переменных. Рассмотрим следующий код, который я выполняю с помощью PyEval_EvalCode
:
myvar = 300
def func():
return myvar
func()
Этот простой код действительно вызывает ошибку, поскольку Python не может найти переменную myvar
из func
. Даже если myvar
находится в локальном словаре во внешней области, Python не копирует его в локальный словарь во внутренней области. Причина этого заключается в следующем:
Всякий раз, когда Python ищет имя переменной, сначала он проверяет locals
, затем проверяет globals
и, наконец, проверяет builtins
. В области модуля locals
и globals
являются САМЫМ словарным объектом. Таким образом, оператор x = 5
в области модуля поместит x
в словарь locals
, который также является словарем globals
. Теперь функция, определенная в области модуля, которая нуждается в поиске x
, не найдет x
внутри функции-области locals
, потому что Python не копирует локали области модуля в локальные области функций. Но это обычно не проблема, потому что он может найти x
в globals
.
x = 5
def foo():
print(x) # This works because 'x' in globals() == True
Это только с вложенными функциями, что Python, похоже, копирует локальные локальные объекты во внутренние локали. (Это также кажется ленивым, только если они необходимы во внутренней области.)
def foo():
x = 5
def bar():
print(x) # Now 'x' in locals() == True
bar()
Таким образом, результатом всего этого является то, что при выполнении кода в области модуля вы должны убедиться, что ваш глобальный словарь и локальный словарь являются ТОЛЬКО объектом, иначе функции области видимости модуля не смогут получить доступ к переменным области видимости модуля.
Но в моем случае я не хочу, чтобы глобальный словарь и локальный словарь были одинаковыми. Поэтому мне нужно каким-то образом сказать интерпретатору Python, что я выполняю код в области функций. Есть ли способ сделать это? Я просмотрел PyCompileFlags
, а также дополнительные аргументы PyEval_EvalCodeEx
и не могу найти способ сделать это.