简体   繁体   English

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

[英]Why globals() inside a function can't update variables in interactive shell?

Today I wrote an "alias import function" for myself, because I need to write a script to do variable value checks for different python files. 今天我为自己写了一个“别名导入函数”,因为我需要编写一个脚本来对不同的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]

The weird thing is, if I start a Python interactive shell, I can't import things by using this function. 奇怪的是,如果我启动一个Python交互式shell,我就无法使用这个函数导入东西。 But by using its content outside of the function, it works. 但是通过在函数之外使用它的内容,它可以工作。

>>> 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'
>>>

I did 3 more experiments after: 之后我又做了3次实验:

    • Do python -i test.py python -i test.py
    • import zen_basic in interactive shell 在交互式shell中import zen_basic
    • call from_module_import_alias function, failed. 调用from_module_import_alias函数,失败。
    • Do python -i zen_basic.py python -i zen_basic.py
    • call from_module_import_alias function, success. 调用from_module_import_alias函数,成功。
    • add code which import zen_basic and call the from_module_import_alias function to test.py 添加import zen_basic代码并将from_module_import_alias function调用到test.py
    • Do python -i test.py , success python -i test.py ,成功

What's the reason that directly using from_module_import_alias function in a Python interactive shell failed? 在Python交互式shell中直接使用from_module_import_alias函数失败的原因是什么?

You are updating the wrong globals. 您正在更新错误的全局变量。 You are updating the globals of your zen_basic module, not the __main__ module (the namespace for your script or the interactive interpreter). 您正在更新zen_basic模块的全局变量,而不是__main__模块(脚本或交互式解释器的命名空间)。 The globals() function always returns the globals of the module in which the code was defined, not the module that called your function. globals()函数总是返回定义代码的模块的全局变量,而不是调用函数的模块。

You'd have to retrieve the globals of the calling frame. 你必须检索调用帧的全局变量。 Note that it rarely is advisable to modify the globals of the calling frame, but if you must then you can retrieve the calling frame by using the sys._getframe() function : 请注意,很少修改调用帧的全局变量,但如果必须,则可以使用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]

In your experiments, python -i zen_basic.py runs zen_basic as the main script entry, and thus globals() references the __main__ module. 在您的实验中, python -i zen_basic.pyzen_basic作为主脚本条目运行,因此globals()引用__main__模块。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM