如何动态导入模块?

13

我正在尝试在Python中动态导入模块。目前,我有一个名为“modules”的目录,里面有两个文件(mod1.pymod2.py)。它们是简单的测试函数,用于返回时间(例如,mod1.what_time('now')返回当前时间)。

从我的主应用程序中,我可以按如下方式导入:

sys.path.append('/Users/dxg/import_test/modules')
import mod1

然后,我可以执行:

mod1.what_time('now') 

这个程序可以正常运行。

我并不总是知道目录中有哪些模块可用。我想按照以下方式导入:

tree = []
tree = os.listdir('modules')

sys.path.append('/Users/dxg/import_test/modules')

for i in tree:
  import i

然而,我遇到了错误:

ImportError: No module named i

我错过了什么?


1
相关内容请参考https://dev59.com/QlkR5IYBdhLWcg3w0AKy - Uriel
上述提到的问题有助于理解为什么它不起作用,但并不能确定是否有解决方案使其正常工作。 - Dan G
看一下__import__()函数。 - martineau
我的这个答案展示了如何使用__import __()listdir()。它做的比你想要的多,但应该很容易解决。 - martineau
如果你不知道有哪些模块可用,你的代码怎么知道要使用它们呢? - martineau
@martineau; 在这个应用程序中,每个模块都是一个测试用例。每个模块(测试用例)都有一个名为execute_test()的标准布局主函数。因此,基于文件名作为模块名,我们可以触发测试用例执行。例如:模块文件名为create_user.py;一旦导入,我们可以使用create_user.execute_test()来触发它。 - Dan G
2个回答

14

import指令不能使用变量内容(如字符串)(详见这里的扩展说明),而是要使用文件名。 如果您想要动态导入,可以使用importlib.import_module方法:

import importlib
tree = os.listdir('modules')

...

for i in tree:
    importlib.import_module(i)

注意:

  • 如果你要从一个不包含在Lib目录或当前目录中的模块中导入,那么添加路径是没有用的(详见上述链接)。最简单的解决方案是将这个目录(模块)转化为一个包(只需在其中放置一个空的__init__.py文件),然后调用importlib.import_module('..' + i, 'modules.subpkg')或使用__import__方法。

  • 你也可以查看这个问题,它讨论了类似的情况。


-2

你可以实现类似于你所提出的想法,但这将涉及到一些不符合Python风格的代码。我不建议这样做:

dynamic_imports = dict()
for filename in tree:
    name = filename.replace('.py', '')
    dynamic_imports[name] = __import__(name)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接