Reputation: 4821
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.
# 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. 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:
python -i test.py
import zen_basic
in interactive shell from_module_import_alias
function, failed. python -i zen_basic.py
from_module_import_alias
function, success.import zen_basic
and call the from_module_import_alias function
to test.py
python -i test.py
, successWhat's the reason that directly using from_module_import_alias
function in a Python interactive shell failed?
Upvotes: 4
Views: 378
Reputation: 1125368
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). The globals()
function always returns the globals of the module in which the code was defined, not the module that called your function.
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:
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.
Upvotes: 6