从模块中动态导入所有内容(*)

31 投票
3 回答
6120 浏览
提问于 2025-04-16 06:41

我有一个Python模块,我想根据模块名称的字符串动态导入它。通常我会使用 importlib__import__,这样做效果不错,因为我知道想从模块中导入哪些对象。但是,有没有办法可以像 import * 那样动态导入所有内容呢?或者有没有更好的方法?

我知道一般来说使用 import * 是不太好的做法,但我想导入的模块是自动生成的,我无法知道具体哪个模块里包含我需要的类。

谢谢。

3 个回答

4

以下内容是非常不好的,可能会让你受到惩罚,甚至更糟糕。

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

对于字典,可以使用 update 方法:

globals().update(importlib.import_module('some.package').__dict__)

需要注意的是,使用 a_module.__dict__from a_module import * 是不一样的。前者会把所有的名字都“导入”进来,而不仅仅是 __all__ 中的名字或者那些不以 _ 开头的名字。

4

我写了一些很糟糕的代码,虽然在 Python 2.6 中能运行,但我不确定这样做是否聪明。也许这里有其他人能给出一些见解:

test = __import__('os',globals(),locals())
for k in dir(test):
    globals()[k] = test.__dict__[k]

你可能需要在这里加个检查,以确保你不会覆盖全局命名空间中的任何东西。其实你可以不使用 globals 部分,而是直接查看每个动态导入的模块,找出你感兴趣的类。这样做可能比把所有导入的东西都放到全局命名空间要好得多。

举个例子,假设你的类叫做 Request,来自 urllib2。

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

撰写回答