在 python 中动态加载包

Dynamically load a package in python

假设我有两个几乎相同的python 包mymod 版本,即mymod0 和mymod1。这些包中的每一个都有文件 init.py 和 foo.py,并且 foo.py 有一个函数 printme()。调用 mymod0.foo.printme() 将打印 "I am mymod0",调用 mymod1.foo.printme() 将打印 "I am mymod1"。到目前为止一切顺利。

但现在我需要动态导入 mymod0 或 mymod1。用户将向脚本输入 0 或 1(作为变量 "index"),然后我可以创建 packageName="mymod"+str(index)

我试过这个:

module=importlib.import_module(module_name)
module.foo.printme()

但是我得到这个错误: AttributeError: 'module' 对象没有属性 'foo'

我如何指定包现在应该被称为模块,以便 module.foo.printme() 可以工作?

更新:所以看起来最简单的解决方案是使用 exec() 函数。这样我就可以像这样动态创建一个导入语句:

cmdname="from mymod%s import foo" % index
exec(cmdname)

然后:

foo.printme()

这似乎有效。

How can I specify the the package should now be referred to as module so that module.foo.printme() will work?

您必须确保 <module_name>.__init__foo 导入模块的命名空间:

#./<module_name>/__init__.py
import foo

那么你可以

module=importlib.import_module(module_name)
module.foo.printme()

But now I need to dynamically import either mymod0 or mymod1.

请注意,这只适用于第一次,因为 python 缓存加载的模块。如果自程序启动以来模块发生了变化,请使用 reload function 函数。请注意:有几个与此相关的警告,它可能最终不会按照您的预期进行。

How can I recreate this dynamically?

for i in range(0,2):
   module_name = 'mymod%s' % i
   module=importlib.import_module(module_name)
   module.foo.printme()