Python中模块的延迟加载

6 投票
3 回答
1241 浏览
提问于 2025-04-16 06:18

我正在写一个Python小程序,用来从科学仪器获取数据,我想找出管理设备“驱动程序”的最佳方法。

每个驱动程序在我的程序包中都有一个单独的Python模块。它们都实现了一些标准接口,但大多数情况下,它们只是一个庞大的命令列表(和函数映射),这些都是针对每个设备和总线的特定内容。从长远来看(我为我的实验室团队写这个,计划支持几十个设备),我想避免一次性加载所有驱动程序。相反,我希望在运行时读取一个模块列表到一个字典或列表中,然后只有在真正需要时才加载它们。

当用户想使用一个新设备时,他会选择要使用的驱动程序,并将名称传递给驱动程序子系统。这个子系统会检查该驱动程序是否在已加载模块的列表中,如果没有,它就会调用__import__函数来加载这个驱动程序,然后用这个驱动程序实例化一个设备对象,并把它交给用户使用。

我的问题是:获取所有模块的相对列表的最佳方法是什么?我的意思是,如果我知道驱动程序位于..drivers,有没有办法获取该子包中模块的整洁列表?举个例子:通常我会调用from ..drivers import driver_name来导入模块,但由于我不能保证自己在包目录中,所以不能仅仅使用os来获取模块名称的列表。

无论如何,任何想法(甚至可能是实现我想要的更好方法——可加载的“驱动程序”)都将不胜感激。

3 个回答

0

为什么不把所有的驱动程序打包成一个包呢?这样你就可以

import drivers
drivers.load("device1")

在这里,load 函数可以保持设备名称和包内模块之间的对应关系。这样你就可以在需要的时候动态地导入每个所需的模块……

3

有一个叫做 pkgutil 的东西,它里面有一个功能叫 iter_modules。需要注意的是,虽然 Python 2 的文档 没有提到这个功能,但我在 Python 2.6 上用得很好。

你也可以手动实现这个功能,使用 __file__os.pathos.listdir 这些工具。

3

如果你知道驱动程序包的位置,那么你可以直接使用驱动文件夹的绝对路径。

我觉得更好的方法是列出你程序中所有已知的驱动程序,可能还可以加上一些额外的信息,这样用户就能更容易地选择它们。你可以让驱动程序自己注册,或者如果你知道可能的位置,也可以自己注册。让驱动程序自己注册的一个好处是,驱动包目录里可能还有其他的 Python 文件。

编辑

要让一个驱动程序“自我注册”,你可以这样做:

if __name__ == "__main__":
    import mamapackage
    mamapackage.register("thisdriver", 
               os.path.abspath(__file__), 
               "A description of this driver")

然后在你自己的包里,提供一个“注册”函数,用来更新驱动程序的列表,包括它们的位置和描述(一开始可以用一个简单的文本文件)。

撰写回答