为什么函数内的globals()无法更新交互式shell中的变量?

Zen*_*Zen 4 python

今天我为自己写了一个"别名导入函数",因为我需要编写一个脚本来对不同的python文件进行变量值检查.

# filename: zen_basic.py

import importlib
def from_module_import_alias(module_name, var_name, alias):
    """ equal to from module import a as b """
    agent = importlib.import_module(module_name)
    globals()[alias] = vars(agent)[var_name]
Run Code Online (Sandbox Code Playgroud)

奇怪的是,如果我启动一个Python交互式shell,我就无法使用这个函数导入东西.但是通过在函数之外使用它的内容,它可以工作.

>>> from zen_basic import *
>>> module_name = 'autor'
>>> var_name = 'food'
>>> alias = 'fd'
>>> from_module_import_alias(moduele_name, var_name, alias)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'moduele_name' is not defined
>>> from_module_import_alias(module_name, var_name, alias)
>>> fd
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'fd' is not defined
>>> agent = importlib.import_module(module_name)
>>> globals()[alias] = vars(agent)[var_name]
>>> fd
'cake'
>>>
Run Code Online (Sandbox Code Playgroud)

之后我又做了3次实验:

    • python -i test.py
    • import zen_basic 在交互式shell中
    • 呼叫from_module_import_alias功能,失败.
    • python -i zen_basic.py
    • 呼叫from_module_import_alias功能,成功.
    • 添加代码import zen_basic并调用from_module_import_alias functiontotest.py
    • python -i test.py,成功

直接from_module_import_alias在Python交互式shell中使用函数失败的原因是什么?

Mar*_*ers 5

您正在更新错误的全局变量.您正在更新zen_basic模块的全局变量,而不是__main__模块(脚本的命名空间或交互式解释器).该globals()函数始终返回定义代码的模块的全局变量,而不是调用函数的模块.

你必须检索调用帧的全局变量.请注意,很少修改调用帧的全局变量,但如果必须,则可以使用以下sys._getframe()函数检索调用帧:

import sys

def from_module_import_alias(module_name, var_name, alias):
    """ equal to from module import a as b """
    agent = importlib.import_module(module_name)
    calling_globals = sys._getframe(1).f_globals
    calling_globals[alias] = vars(agent)[var_name]
Run Code Online (Sandbox Code Playgroud)

在您的实验中,作为主脚本条目python -i zen_basic.py运行zen_basic,从而globals()引用该__main__模块.