Python exec() 函数在 2.7 以上版本中损坏?错误: 'name' not defined

标签 python python-3.x python-2.7 exec

我发现了 python exec() 函数的奇怪行为。这是代码:

variables = {
    ('foo', 6),
    ('bar', 42)
}

def func():
    for varData in variables:
        varName, varValue = varData
        localVarToEvaluate = varName + ' = varValue'
        try:
            #exec(localVarToEvaluate, globals(), locals())
            exec(localVarToEvaluate)
        except Exception as err:
            print(str(err))

        if varName not in locals():
            print("Variable names '", varName, "can't be found in local scope!")

    if 'foo' in locals():
        print("'foo' OK:", foo)  # exception here
    else:
        print("'foo' not available!")

    if 'bar' in locals():
        print("'bar' OK:", bar)
    else:
        print("'bar' not available!")

func()

我希望变量 foobarexec() 调用结束时创建并打印,情况就是这样Python 2.7。上面的所有内容(在 3.3、3.4、3.6 和 3.7 上测试)都会抛出异常,即 foo 未定义:

Exception has occurred: NameError
    name 'foo' is not defined

这里奇怪的是,通过运行 locals()globals() 可以看到 foobardir() (也由 if 语句确认),但是,代码/解释器看不到它。 更奇怪的是,调试此脚本并解析任何变量均成功(我已在 # exception here 上设置了断点,并使用 VS Code 在调试窗口中键入 foo foo 已正确解析,值为“6”。

如果相同的代码(函数 func() 内的内容)未包装在函数中,则这将按预期工作,foobar打印出来。

知道这里发生了什么吗?

<小时/>

更新:我进一步简化了这个问题:

# take 1, create local variable 'foo' with value 6. Not in function.
varName = 'foo'
varValue = 42
localVarToEvaluate = varName + ' = varValue'

try:
    exec(localVarToEvaluate)
except Exception as err:
    print(str(err))

if 'foo' in locals():
    # print(locals()['foo']) # (1)
    # print(foo)  # (2)
    print("'foo' OK:", foo)  # (3)


# take 2, create local variable 'bar' with value 42
def func2():
    varName = 'bar'
    varValue = 42
    localVarToEvaluate = varName + ' = varValue'

    try:
        exec(localVarToEvaluate)
    except Exception as err:
        print(str(err))

    if 'bar' in locals():
        # print(locals()['bar']) # (1)
        # print(bar)  # (2)
        #print("'bar' OK:", bar)  # (3)
        pass # uncomment any line above

func2()

当这段代码执行时,首先:

'foo' OK: 6

被打印,然后引发此异常:

Exception has occurred: NameError
name 'bar' is not defined
  ...

请注意,两个代码是相同的,除了“bar”变量是在函数 func2() 内部创建的。

我感兴趣的不是解决方法,而是解释,为什么会这样以及为什么点(1)有效,而(2)和(3)则无效。请注意,bar 变量在 locals() 中可见,但无法通过直接调用来访问它 - 但前提是它是在函数内部创建的!

最佳答案

I've reported a bug on a Python Issue Tracker官方答案是:

This is currently by design, which means 3.8 is likely the only viable place it can change. It's also not Windows specific so I removed that component (people may remove themselves from nosy).
...
Currently it's basically a read-only proxy, as locals are optimized within functions which is why you can't see updates via the duct.

底线,以这种方式使用的 exec() 在函数内部是无用的。

关于Python exec() 函数在 2.7 以上版本中损坏?错误: 'name' not defined,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55239875/

相关文章:

python - 支持类的 .send() 吗?

python - 如何在 Django 模板中获取字典键和值?

python - 如果一个字符串与另一个字符串共享所有字符,包括 double Python-3.x,则返回 bool

python - while 异步中的 True 循环会阻止代码的其他部分工作 Discord.py

python-2.7 - Caffe 到 Tensorflow(Ethereon 的 Kaffe): TypeError: Descriptors should not be created directly,,但仅从其父级检索

python - 具有透明度的 mayavi 屏幕截图

python - Python 中的 Voronoi 分割

python - 创建随机值并将其传递给具有硬边界的 Pandas 数据帧

python - ImportError:使用 manage.py 时没有名为 django.core.management 的模块

python - 为什么 subprocess.call 仅当参数在数组中分隔时才适用于任何字符串?