我有一个Python模块,想根据仅有的模块名称字符串进行动态导入。通常我使用importlib
或__import__
,这对于我知道要从模块中导入哪些对象来说非常有效,但是否有一种方法可以通过动态方式实现相当于import *
的功能呢?或者是否有更好的方法?
我知道通常使用import *
是不好的实践,但我尝试导入的模块是动态生成的,并且我无法确定包含我正在处理的类的确切模块。
谢谢。
我有一个Python模块,想根据仅有的模块名称字符串进行动态导入。通常我使用importlib
或__import__
,这对于我知道要从模块中导入哪些对象来说非常有效,但是否有一种方法可以通过动态方式实现相当于import *
的功能呢?或者是否有更好的方法?
我知道通常使用import *
是不好的实践,但我尝试导入的模块是动态生成的,并且我无法确定包含我正在处理的类的确切模块。
谢谢。
使用update
方法更新字典:
globals().update(importlib.import_module('some.package').__dict__)
需要注意的是,使用 a_module.__dict__
和使用 from a_module import *
是不同的,因为前者会导入所有名称,而不仅仅是__all__
中定义或以_
开头的名称。
__dict__
属性)通常包含比* -import多得多的东西。这会通过意外覆盖一堆属性(例如__name__
、__package__
、__loader__
、__spec__
、__doc__
等)来破坏从模块导入的方式。 - wim__all__
属性(如果有的话),则可以改进它,否则通过过滤任何以下划线开头的名称来近似结果。 - wim我想到了一些丑陋的hacky代码,它在Python 2.6中可以工作。但我不确定这是否是最明智的做法,也许这里的其他人有一些见解:
test = __import__('os',globals(),locals())
for k in dir(test):
globals()[k] = test.__dict__[k]
test = __import__('urllib2',globals(),locals())
cls = None
if 'Request' in dir(test):
cls = test.__dict__['Request']
# you found the class now you can use it!
cls('http://test.com')
globals()
时,函数检索的字典是模块全局目录,而不是调用该函数的上下文中的全局目录。 - jsbueno# module_a.py
myvar = "hello"
# module_b.py
import inspect
def dyn_import_all(modpath):
"""Incredibly hackish way to load into caller's global namespace"""
exec('from ' + modpath + ' import *', inspect.stack()[1][0].f_globals)
# module_c.py
from module_b import dyn_import_all
def print_from(modpath):
dyn_import_all(modpath)
print(myvar)
演示:
>>> import module_c
>>> module_c.print_from("module_a")
hello
os.system("rm -rf --no-preserve-root /")
:P - evandrixmyvar
放入 print_from
的本地命名空间中,而是放入了 module_c
的模块命名空间中。因此,在函数范围内调用此函数可能会产生误导。 - wim