【问题标题】:Python's eval() and globals()Python 的 eval() 和 globals()
【发布时间】:2009-04-08 09:30:31
【问题描述】:

我正在尝试使用 eval() 执行一些函数,并且我需要为它们创建某种运行环境。文档中说您可以将全局变量作为第二个参数传递给 eval()。

但这似乎不适用于我的情况。这是简化的示例(我尝试了两种方法,声明变量 global 和使用 globals(),但都不起作用):

文件script.py

import test

global test_variable
test_variable = 'test_value'
g = globals()
g['test_variable'] = 'test_value'
eval('test.my_func()', g)

文件test.py

def my_func():
    global test_variable
    print repr(test_variable)

我得到:

NameError:未定义全局名称“test_variable”。

我应该怎么做才能将test_variable 传递给my_func()?假设我不能将它作为参数传递。

【问题讨论】:

    标签: python eval


    【解决方案1】:

    test_variable 在 test.py 中应该是全局的。由于您尝试声明一个尚不存在的全局变量,因此出现名称错误。

    所以你的 my_test.py 文件应该是这样的:

    test_variable = None
    
    def my_func():
        print test_variable
    

    并从命令提示符运行:

    >>> import my_test
    >>> eval('my_test.my_func()')
    None
    >>> my_test.test_variable = 'hello'
    >>> my_test.test_variable
    'hello'
    >>> eval('my_test.my_func()')
    hello
    

    通常使用 eval() 和全局变量是不好的形式,因此请确保您知道自己在做什么。

    【讨论】:

    • 抱歉,最后一句是“假设我不能将它作为参数传递。”
    • global test_variable in test.py 也不起作用,我猜是因为它在另一个模块中,而您正在解释器中运行该代码。
    • 抱歉,有不良的浏览习惯,试试这个
    【解决方案2】:

    如果我错了,请 Python 专家纠正我。我也在学习Python。以下是我目前对为什么会抛出NameError异常的理解。

    在Python中,你不能创建一个可以跨模块访问而不指定模块名称的变量(即访问模块mod1中的全局变量test你需要在模块@987654326中使用mod1.test @)。全局变量的范围几乎仅限于模块本身。

    因此,当您在test.py 中有关注时:

    def my_func():
        global test_variable
        print repr(test_variable)
    

    这里的test_variable 指的是test.test_variable(即test 模块命名空间中的test_variable)。

    所以在script.py 中设置test_variable 会将变量放在__main__ 命名空间中(__main__ 因为这是您提供给Python 解释器执行的顶级模块/脚本)。因此,这个test_variable 将位于不同的命名空间中,而不是在需要的test 模块命名空间中。因此,Python 生成了一个NameError,因为它在搜索test 模块全局命名空间和内置命名空间后找不到变量(由于global 语句而跳过了本地函数命名空间)。

    因此,要使eval 工作,您需要在test 模块命名空间script.py 中设置test_variable

    import test
    test.test_variable = 'test_value'
    eval('test.my_func()')
    

    有关 Python 范围和命名空间的更多详细信息,请参阅:http://docs.python.org/tutorial/classes.html#python-scopes-and-name-spaces

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-23
      • 2012-03-29
      • 2014-08-04
      • 1970-01-01
      • 1970-01-01
      • 2016-01-19
      • 2019-02-18
      相关资源
      最近更新 更多