具有函数链的Python exec产生NameError

问题描述

考虑以下脚本,该脚本使用exec定义两个函数,其中一个调用一个函数

def run_code():
  code = """
def foo():
  print('foo')
  return 1

def bar():
  print('bar calls foo')
  return 1 + foo()

result = bar()
"""

  exec(code,globals(),locals())
  print('Result: {}'.format(locals()['result']))

run_code()

我希望看到以下输出

bar calls foo
foo
Result: 2

但是,相反,我得到以下输出+ stacktrace:

bar calls foo
Traceback (most recent call last):
  File "minimal.py",line 17,in <module>
    run_code()
  File "minimal.py",line 14,in run_code
    exec(code,locals())
  File "<string>",line 10,in <module>
  File "<string>",line 8,in bar
NameError: name 'foo' is not defined

有趣的是,如果将run_code内容移到模块级别,则可以正常工作。但是,如果我随后用新的空字典替换globals()locals(),它将再次中断。我还知道,将def foo放入bar的身体中将使其正常工作。

为什么会发生此错误,正确的解决方法是什么?

(我知道exec通常不被接受。我有充分的理由使用它。)

解决方法

来自documentation

如果提供的话,本地变量可以是任何映射对象。记住在模块 级别,全局变量和本地变量是同一词典。如果高管得到两个 将对象作为全局对象和局部对象分开,代码将作为 如果它嵌入在类定义中。

并且类定义不会创建封闭范围,请注意,这就是为什么不使用time_dict = { "CS101": { "Time": "8:00 a.m." },"CS102": { "Time": "9:00 a.m." },"CS103": { "Time": "10:00 a.m." },"NT110": { "Time": "11:00 a.m." },"CM241": { "Time": "1:00 p.m." },} 不能从另一个方法调用一个方法的原因。因此 just 通过self字典。或将两个相同的dict传递给两个参数。

globals()
,
    cout<<"\n\n*The game is being played*\n\n"<<endl;
    cout<<"Guess the number between 1 to 100\n"<<endl;
    while(true)
    {
        cout<<"Input number:";
        int maxNum = 100;
        int leastNum = 1;
        int guess;
        cin>>guess;
        if(guess < leastNum || guess > maxNum)
        {
            cout<<"It must be higher or equal than"<<" "<<leastNum<<endl<<"and it must not exceed"<<" "<<maxNum<<endl;
        }
        else if(guess < RanNum)
        {
            cout<<"\nYour number is LOW\n"<<endl;
        }
        else if(guess > RanNum)
        {
            cout<<"\nYour number is HIGH\n"<<endl;
        }
        else
        {
            cout<<"\nYour correct!";
            again();
            break;
        }
    }
}
int main()
{
    int choice;
    cout<<"Want to play the game?\n\n"<<endl;
    cout<<"Type 1 if want to play"<<endl<<"Type 0 if not\n\n"<<endl;
    cout<<"Input here:";
    cin>>choice;
    switch(choice)
    {
    case 1 :
        play_game();
        break;
    case 0 :
        cout<<"\nOh ok see ya!\n\n";
        break;
    default :
        cout<<"\n\nThe choices are\n\n1 or 0 \n\nplease try again\n\n";
        break;
    }
    return 0;
}

输出:

code = """  
def foo():
  print('foo')
  return 1

def bar():
  global foo;
  print('bar calls foo')
  return 1 + foo()

result = bar()
"""
def run_code():
    exec(code,globals(),locals())
    print('Result: {}'.format(locals()['result']))


run_code()