
3.3.2 模块空间与主程序
当使用import或from…import 语句导入模块时,Python会开辟一个新的空间,在这个新空间中读取模块中的程序并运行程序,这个空间叫模块空间。如果遇到可执行的语句,Python会执行这些语句并返回结果,如果模块中只有函数和类,没有可以直接执行的语句,就不会有返回结果。另外,为了测试模块中各函数或类的定义是否准确,需要在模块中加入一些可以执行的程序,模块在导入到另外一个程序中时直接运行可执行的语句是我们不希望的。例如下面的程序有一个定义和调用函数的语句module_test(),还有一个输出语句print("模块测试"),如果执行这个程序,会得到“我在主程序中运行”和“模块测试”,如果把这个程序存盘为sub_module.py文件,并导入其他模块中,会有什么结果呢?

新建立另外一个文件my_run.py,输入“from sub_module import module_test”语句,从sub_module.py中导入module_test()函数,如果运行my_run.py,可以看出Python输出了“我在sub_module模块中运行”和“模块测试”信息,这是我们不希望得到的结果。其实我们只想导入一个函数,并不想执行模块中其他语句。

为了防止出现上面的情况,可以根据程序运行的空间名字决定是否执行模块中的可执行语句。Python中有个变量__name__,它记录程序执行的空间名字,对于Python直接运行的程序,__name__的值是”__main__”,表示主程序,而从主程序导入模块时,新建立的空间是模块空间,模块空间的名字和模块名字相同,这从上面的返回值中可以看出。现把sub_ module.py程序修改如下,运行这个程序,并不影响程序的正确结果,如果回到my_run.py并运行my_run.py,也不会有任何输出。

现把my_run.py修改如下,可以看出即便是用了“from sub_module import module_test”语句,而不是“importsub_module”语句,函数module_test()的运行空间还是模块空间。通常在主程序中会加入“if__name__=="__main__":”语句,表示整个程序的入口。需要注意的是,如果两个模块空间中有两个数据的名字相同,用import moduleName形式导入模块,并不影响程序的正确运行,因为引用模块中的数据需要加入“moduleName.”前缀;而如果用from moduleName import member形式直接导入数据,后读入的数据会覆盖先导入的数据。
