2015-07-03 55 views
4

今天我爲自己寫了一個「別名導入函數」,因爲我需要編寫一個腳本來爲不同的python文件進行變量值檢查。爲什麼函數中的globals()不能更新交互式shell中的變量?

# 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] 

奇怪的是,如果我啓動一個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' 
>>> 

我做了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 functiontest.py
    • python -i test.py,成功

那是什麼,直接使用from_module_import_alias功能在Python交互shell的原因失敗了嗎?

回答

5

您正在更新錯誤的全局變量。您正在更新zen_basic模塊的全局變量,而不是__main__模塊(腳本的名稱空間或交互式解釋器)。 globals()函數總是返回定義代碼的模塊的全局變量,而不是調用函數的模塊。

你必須檢索調用框架的全局變量。需要注意的是它很少是明智的修改調用框架的全局變量,但如果你必須那麼你可以通過使用sys._getframe() function檢索調用框架:

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] 

在你的實驗中,python -i zen_basic.py運行zen_basic爲主要腳本條目,因此globals()引用__main__模塊。

相關問題