模块导入与重载——导入与重载基础

未匹配的标注

简言之,每个以 .py 扩展名结尾的Python源码文件都是一个模块。让文件成为模块是不需要特殊代码或语法的:任何文件都可以。其他文件能通过导入那个模块(导入操作本质上是加载另一个文件并且授予对那个文件内容的访问权)来获得模块所定义的东西。通过模块的属性(一个将在下一部分定义的术语),模块的内容对外部世界可用。

这个基于模块的服务模型被证明是Python 中程序架构下的核心理念。更大的程序通常采用多模块文件的形式,从其他模块文件导入工具。这些模块的其中一个被设计为主或顶层文件,或”脚本“——启动来开始整个程序的文件,它如常逐行运行。在这个级别下面,是所有导入模块的模块。

本书后面将详细深入研究这种架构问题。本章最关注的是导入操作将运行正被加载的文件中的代码作为最后一步(注:也就是被导入文件中的代码将在对应的 import语句被运行时被执行)。因为这个,导入文件也是另一个启动它的方式。

比如,如果开启一个交互式会话(从系统命令行或其他),可以用一个简单的导入运行之前创建的 script1.py 文件:

C:\code> C:\python33\python
>>> import script1
win32
1267650600228229401496703205376
Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam!

这是可以的,但默认一个会话只能一次(事实上,是进程——一个程序运行)。在第一次导入后,随后的导入无效,即使你在另一个窗口再次修改并保存了模块的源文件:

*...Change script1.py in a text edit window to print 2 * 16...

>>> import script1
>>> import script1

设计就是这样的;导入是一个太昂贵的操作以至于不能在一个程序运行中对每个文件重复超过一次。在第22章将学到,导入必须找到文件,编译它们为字节码,再运行代码。

如果真的想强制Python再次在同一个会话中运行文件,而不停止和重启会话,需要使用在 imp 标准库模块中可用的 reload 函数(此函数在 Python 2.X 也是一个简单的内置函数,但在 3.X 中不是):

>>> from imp import reload # Must load from module in 3.X (only)
>>> reload(script1)
win32
65536
Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam!
<module 'script1' from '.\\script1.py'>
>>>

这里的from 语句简单地从模块中拷贝一个名字出来(关于这点更多见后)。reload 函数本身加载并运行文件代码的当前版本,如果在另一个窗口已经修改并保存,那么会重新加载新的变更内容。

这允许在当前的Python交互式会话中实时编辑并获取最新代码。比如,在这个会话中,在第一次 importreload 调用之间, script1.py中的第二个 print 语句在另一个窗口中被修改为 print(2 ** 16)——因此有了不同的结果。

reload 函数期待一个已经被加载的模块对象的名称,所以在重载一个模块前,必须已经成功的导入过它(如果导入报错,就不能再重载,且必须重新导入)。注意 reload 还期待在模块对象名周围的小括号,然而 import 不需要。 reload 是一个被调用的函数,而 import 是一个语句。

这就是为何必须将模块名传递给 reload 作为小括号中的一个参数的原因,且这是为什么当重载的时候会得到一个额外的输出行——最后一个输出行只是 reload 调用返回值的显示结果,一个Python模块对象。在第16章中将学习更多关于使用函数的知识;就现在来说,一听到”函数“,就记住需要小括号来调用。

注:在 Python 3.12 中, imp 将被移除,使用 importlib 作为代替即可。测试代码如下:

>>> from importlib import reload
>>> reload(script1)
darwin
4294967296
Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam!

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~