Python 使用导入进行动态模块加载有何影响?

Python 使用导入进行动态模块加载有何影响?,python,import,Python,Import,在我的申请中,我有: ... folder_a/ __init__.py a.py folder_b/ __init__.py b1.py b2.py ... 我需要根据变量,比如module_from_b,将模块从文件夹_b动态加载到a.py中。为此,在a.py中,我执行以下操作: 由于这将生活在一个循环中,即被多次调用,我想知道它是否对性能或其他方面有任何影响?如果是这样的话,在保持动态模块加载能力的

在我的申请中,我有:

...
folder_a/
    __init__.py
    a.py
    folder_b/
        __init__.py
        b1.py 
        b2.py
        ...
我需要根据变量,比如module_from_b,将模块从文件夹_b动态加载到a.py中。为此,在a.py中,我执行以下操作:


由于这将生活在一个循环中,即被多次调用,我想知道它是否对性能或其他方面有任何影响?如果是这样的话,在保持动态模块加载能力的同时,是否有任何方法可以缓解这种情况

如果您可能要多次这样做,为什么不检查当前名称空间中是否已经存在该模块,如果不存在,则导入该模块

if 'module_I_need_to_load' not in dir():
    from b import module_I_need_to_load
# Or you can look in vars() instead if you have a
# hell of a lot of modules loaded up as dir is a 
# list and vars is a dictionary which will have a
# faster lookup time when you start having a lot of
# elements
if 'module_I_need_to_load' not in vars():
    from b import module_I_need_to_load

我从来没有对它进行过基准测试,但我相信导入一个模块(无论是动态的还是静态的),这个模块以前已经被导入到运行的解释器中,即使是完全不相关的代码也应该非常便宜。它真正需要做的就是一些成功的字典查找

导入一个新模块当然会运行模块中的所有代码,再加上文件系统搜索来查找它

因此,如果您重复地从一组相对较小的模块中导入动态选择的模块,那么只要您能够在第一次使用每个特定模块时容忍延迟,那么您不应该有太多问题。延迟的多少取决于您的模块;一段时间后,您要导入的几乎所有模块都将被导入,因此_导入_调用将变得便宜

您可能会考虑另一种设计:如果您需要的模块的整个集合是可以预先知道的,无论是静态的还是动态的,那么您可以在循环之前预先导入它们,以预热Python导入的模块集。如果b中没有太多不可用的模块,那么您可以导入b的_uinit__; py.py中的所有模块

这样,导入延迟将在启动时消除,您可以在b包上使用getattr动态获取模块,而无需使用_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):
    ...

模块和其他任何东西一样都是对象,所以您可以将它们存储在列表或对象中,或者您对名称所做的任何操作中。直接传递模块通常比将名称作为模块的代理传递,然后再导入它们更干净。

导入语句以字节码形式表示为对uuu import_uu的调用,这绝对没有什么区别。以下两个是


import关键字使用了uu import\uufunction@JBernardo,因此,即使有大量导入在循环中的模块之间来回切换,性能问题也不会太大?如果模块已经加载,则不会再次加载,如果这是您要问的,那么-1 Python的导入机制已经做到了这一点。检查模块是否已导入,然后有条件地调用\uuuu import\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。我不太明白你在最后一段中提出的建议。你能用一个例子再详细说明一下吗?另外,对于您的“预热”方法,我是否可以在模块a.py的开头导入包b中的所有内容,以便稍后在循环中调用_import _;时,所有这些模块都已加载。另外,b中的所有模块都是必需的。在我的建议中,我增加了一点关于传递模块而不是名称的内容。2.是的,在a.py开始时导入所有内容会给您带来预热效果;但它也会给您传递模块对象,而不是我的示例中的名称,这样您就不再需要导入了。我已经用Python编程好几年了,以前我多次使用动态选择的模块,但我从来都不需要导入。
from folder_b import b1, b2, b3, b4

for module in [b1, b2, b3, b4]:
    function_using_module(module)

def function_using_module(module):
    ...
import spam
spam = __import__('spam', globals(), locals(), [], -1)