返回介绍

过渡性模块重载

发布于 2024-01-29 22:24:15 字数 1746 浏览 0 评论 0 收藏 0

我们在第22章学习了模块重载,这是选择代码中的修改而不需要停止或重新启动一个程序的一种方式。当我们重载一个模块时,Python只重新载入特殊模块的文件,它不会自动重载那些为了导入要重载文件的模块。

例如,如果要重载某个模块A,并且A导入模块B和C,重载只适用于A,而不适用于B和C。A中导入B和C的语句在重载的时候重新运行,但是,它们只是获取已经载入的B和C模块对象(假设它们之前已经导入了)。在实际的代码中,文件A.py如下:

默认情况下,这意味着你不能依赖于重载来过渡性地选择程序中的所有模块中的修改;相反,必须使用多次reload调用来独立地更新子部分。对于交互测试的大系统而言,工作量很大。你可以通过在A这样的父模块中添加reload调用,从而设计自己的系统能够自动重载它们的子部分,但是,这会使模块的代码变复杂。

一种更好的办法是,编写一个通用的工具来自动进行过渡性重载,通过扫描模块的__dict__属性并检查每一项的type以找到要重新载入的嵌套模块。这样的一个工具函数应该递归地调用自己,来导航任意形式的导入依赖性链条。模块__dict__属性在前面已介绍过,并且第9章介绍过type调用,我们只需要把两种工具组合起来。

例如,下面列出的模块reloadall.py有一个reload_all函数来自动地重载一个模块,以及该模块导入的每个模块等,所有通往每个导入链条最底端的通路都被考虑到。它使用字典来记录已经重载的模块,递归地遍历导入链条,以及标准库的types模块,该模块直接为内置类型预定义type结果。访问字典的技术在这里用来在导入是递归或冗余的时候避免循环,因为模块对象可以是字典键(正如我们在第5章学习过的,如果我们使用visited.add(module)来插入的话,一个集合将提供类似的功能):

要使用这一工具,导入其reload_all函数并将一个已经载入的模块的名称传递给它。当文件独立地运行,其自测试代码将会测试自己,它必须导入自己,因为它自己的名字并没有在没有一个导入的文件中定义(这段代码在Python 3.0和Python 2.6中都有效,并且打印出相同的输出,因为我们已经在print中使用了+而不是一个逗号):

如下是这个模块对于Python 3.0下的某些标准库模块工作的情况。注意,o s是如何由tkinter导入的,但tkinter在os之前已经导入了sys(如果想要在Python 2.6下测试这段代码,用Tkinter替换tkinter):

如下的会话展示了常规重载和过渡性重载的对比效果——除非使用过渡性工具,否则重载不会选取对两个嵌套的文件的修改:

要更深入地了解,自己研究并体验这个示例,它是你可能想要添加到自己的源代码库中的另一个可导入工具。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文