gpt4 book ai didi

python - C Python : Running Python code within a context

转载 作者:太空狗 更新时间:2023-10-29 17:20:35 25 4
gpt4 key购买 nike

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。在模块范围localsglobals 是同一个字典对象。所以在模块范围内的语句 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 对象作为globalslocals 传递:

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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com