- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
Python C API 函数 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 无法从 func
中找到变量 myvar
。即使 myvar
位于外部作用域的本地字典中,Python 也不会将其复制到内部作用域的本地字典中。原因如下:
每当 Python 查找变量名时,首先检查 locals
,然后检查 globals
,最后检查 builtins
。在模块范围,locals
和globals
是同一个字典对象。所以在模块范围内的语句 x = 5
会将 x
放在 locals
字典中,这也是 globals
词典。现在,在模块作用域定义的需要查找 x
的函数将不会在函数作用域 locals
中找到 x
,因为 Python 不会t 将模块范围的局部变量复制到函数范围的局部变量中。但这通常不是问题,因为它可以在 globals
中找到 x
。
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
的附加参数,但找不到任何方法来执行此操作。
最佳答案
Python 实际上不会将外部作用域局部变量复制到内部作用域局部变量; locals
的文档状态:
Free variables are returned by locals() when it is called in function blocks, but not in class blocks.
这里的“自由”变量是指被嵌套函数关闭的变量。这是一个重要的区别。
针对您的情况,最简单的解决方法就是将相同 dict 对象作为globals
和locals
传递:
code = """
myvar = 300
def func():
return myvar
func()
"""
d = {}
eval(compile(code, "<str>", "exec"), d, d)
否则,您可以将代码包装在一个函数中并从编译对象中提取它:
s = 'def outer():\n ' + '\n '.join(code.strip().split('\n'))
exec(compile(s, '<str>', 'exec').co_consts[0], {}, {})
关于python - C Python : Running Python code within a context,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12265756/
我是一名优秀的程序员,十分优秀!