C Python: запуск кода Python в контексте
API-функция Python CPyEval_EvalCode
позвольте вам выполнить скомпилированный код Python. Я хочу выполнить блок кода Pythonas if it were executing within the scope of a function, так что он имеет свой собственный словарь локальных переменных, которые не влияют на глобальное состояние.
Это кажется достаточно простым, поскольку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
, Вmodule scope, 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
Это только сnested функции, которые Python, кажется, копирует локальные локальные области видимости в локальные области видимости. (Это также кажется ленивым, только если они необходимы во внутренней области.)
def foo():
x = 5
def bar():
print(x) # Now 'x' in locals() == True
bar()
Таким образом, результатом всего этого является то, что при выполнении кода наmodule scopeВы ДОЛЖНЫ убедиться, что ваш глобальный словарь и локальный словарь являются ОДНЫМ объектом, в противном случае функции области модуля не смогут получить доступ к переменным области модуля.
Но в моем случае я не хочу, чтобы глобальный словарь и локальный словарь были одинаковыми. Поэтому мне нужен какой-то способ сообщить интерпретатору Python, что я выполняю код в области действия функции. Есть ли способ сделать это? Я посмотрел наPyCompileFlags
а также дополнительные аргументыPyEval_EvalCodeEx
и не могу найти никакого способа сделать это.