我从来没有对它进行基准测试,但我相信导入(无论是动态的还是静态的)一个之前已经导入正在运行的解释器(即使是完全不相关的代码)的模块应该非常便宜。它真正要做的应该是一些(成功的)字典查找。
导入一个新模块当然会运行模块中的所有代码,加上文件系统搜索来找到它。
因此,如果您从一组相对较小的模块中重复导入动态选择的模块,那么只要您可以容忍第一次使用每个特定模块时的延迟(多少延迟取决于您的模块);过了一会儿,几乎所有你要导入的模块都已经被导入了,所以__import__
调用会变得很便宜。
您可能会考虑另一种设计:如果您需要的总模块集是预先知道的(静态或动态),您可以在循环之前预导入它们以“预热”Python 的导入模块集。如果 b 中没有很多不会使用的模块,您可以导入 b's 中的所有内容__init__.py
。
这样,导入延迟将在启动时得到解决,您可以getattr
在 b 包上使用来动态获取您的模块,而不是需要使用__import__
. 如果您要加载如此多的模块以至于您想在循环中分散导入成本,或者如果您有很多模块但只需要相对较少的数量并且很难知道哪些模块在前面,那么这不是一个好的选择时间。
还有另一种可能更好的方法,如果在您确定要导入哪个模块的地方选择一些常量字符串(而不是从配置文件或用户输入中读取的内容),则该方法将起作用。与其将模块的名称向前传递以最终在其他地方导入,为什么不在那里导入模块并将模块本身传递给最终在其他地方使用呢?作为一个虚构的例子,因为我不知道你在做什么,而不是:
for module_name in ['b1', 'b2', 'b3', 'b4']:
function_using_module(module_name)
def function_using_module(module_name):
module = __import__(...)
...
你可以这样做:
from folder_b import b1, b2, b3, b4
for module in [b1, b2, b3, b4]:
function_using_module(module)
def function_using_module(module):
...
模块和其他任何东西一样都是对象,因此您可以将它们存储在列表或对象中,或者您对名称所做的任何事情中。直接传递模块通常比传递名称作为模块的代理然后导入它们更干净。