Python导入模块时的过程
python的import是在程序运行期间执行的,并非像其它很多语言一样是在编译期间执行。也就是说,import可以出现在任何地方,只有执行到这个import行时,才会执行导入操作。且在import某个模块之前,无法访问这个模块的属性。
python在import导入模块时,首先搜索模块的路径,然后编译并执行这个模块文件。虽然概括起来只有两个过程,但实际上很复杂。
前文已经解释了import的模块搜索过程,所以这里大概介绍import的其它细节。
以前面的a.py中导入模块文件b.py为例:
importb
import导入模块时,搜索到模块文件b.py后:
1.首先在内存中为每个待导入的模块构建module类的实例:模块对象。这个模块对象目前是空对象,这个对象的名称为全局变量b。
注意细节:module类的对象,变量b。
输出下它们就知道:
print(b)
print(type(b))
输出结果:
因为b是全局变量,所以当前程序文件a.py中不能重新对全局变量b进行赋值,这会使导入的模块b被丢弃。例如,下面是错误的:
importb
b=3
print(b.x)#已经没有模块b了
另外,因为import导入时是将模块对象赋值给模块变量,所以模块变量名不能是python中的一些关键字,比如if、for等,这时会报错。虽然模块文件名可以为list、keys等这样的内置函数名,但这会导致这些内置函数不可用,因为根据变量查找的作用域规则,首先查找全局变量,再查找内置作用域。也就是说,模块文件的文件名不能是这些关键字、也不应该是这些内置函数名。
File"g:/pycode/new.py",line11
importif
^
SyntaxError:invalidsyntax
2.构造空模块实例后,将编译、执行模块文件b.py,并按照一定的规则将一些结果放进这个模块对象中。
注意细节,编译、执行b.py、将结果保存到模块对象中。
模块第一次被导入的时候,会进行编译,并生成.pyc字节码文件,然后python执行这个pyc文件。当模块被再次导入时,如果检查到pyc文件的存在,且和源代码文件的上一次修改时间戳mtime完全对应(也就是说,编译后源代码没有进行过修改),则直接装载这个pyc文件并执行,不会再进行额外的编译过程。当然,如果修改过源代码,将会重新编译得到新的pyc文件。
注意,并非所有的py文件都会生成编译得到的pyc文件,对于那些只执行一次的程序文件,会将内存中的编译结果在执行完成后直接丢弃(多数时候如此,但仍有例外,比如使用compileall模块可以强制编译成pyc文件),但模块会将内存中的编译结果持久化到pyc文件中。另外,运行字节码pyc文件并不会比直接运行py文件更快,执行它也一样是一行行地解释、执行,唯一快的地方在于导入装载的时候无需重新编译而已。
执行模块文件(已完成编译)的时候,按照一般的执行流程执行:一行一行地、以代码块为单元执行。一般地,模块文件中只用来声明变量、函数等属性,以便提供给导入它的模块使用,而不应该有其他任何操作性的行为,比如print()操作不应该出现在模块文件中,但这并非强制。
总之,执行完模块文件后,这个模块文件将有一个自己的全局名称空间,在此模块文件中定义的变量、函数等属性,都会记录在此名称空间中。
最后,模块的这些属性都会保存到模块对象中。由于这个模块对象赋值给了模块变量b,所以通过变量b可以访问到这个对象中的属性(比如变量、函数等),也就是模块文件内定义的全局属性。
只导入一次
假设a.py中导入了模块b和模块sys,在b.py中也导入了模块sys,但python默认对某个模块只会导入一次,如果a.py中先导入sys,再导入b,那么导入b并执行b.py的时候,会发现sys已经导入了,不会再去导入sys。
实际上,python执行程序的时候,会将所有已经导入的模块放进sys.module属性中,这是一个dict,可以通过下面的方式查看已导入的模块名:
>>>importsys
>>>list(sys.module.keys())
如果某个程序文件中多次使用import(或from)导入同一个模块,虽然不会报错,但实际上还是直接使用内存中已装载好的模块对象。
例如,b.py中x=3,导入它之后修改该值,然后再次导入,发现b.x并不会发生改变:
importb
print(b.x)#3
b.x=33
print(b.x)#33
importb
print(b.x)#33
但是python提供了reload进行多次重复导入的方法,见后文。
使用别名
import导入时,可以使用as关键字指定一个别名作为模块对象的变量,例如:
importbasbb
bb.x=3
print(bb.x)
这时候模块对象将赋值给变量bb,而不是b,b此时不再是模块对象变量,而仅仅只是模块名。使用别名并不会影响性能,因为它仅仅只是一个赋值过程,只不过是从原来的赋值对象变量b变为变量bb而已。
以上内容为大家介绍了Python导入模块时的过程,希望对大家有所帮助,如果想要了解更多Python相关知识,请关注IT培训机构:千锋教育。
相关推荐HOT
更多>>python并集是什么意思?
python并集是什么意思?本文教程操作环境:windows7系统、Python3.9.1,DELLG3电脑。以属于A或属于B的元素为元素的集合成为A与B的并集。1、概念...详情>>
2023-11-14 16:44:05python框架是什么
python框架是什么1、说明Python开发框架大大减少了开发者不必要的重复劳动,提高了项目开发效率的同时,还使得创建的程序更加稳定。2、框架类型...详情>>
2023-11-14 14:57:51pythonlstrip()截掉字符
python中lstrip()截掉字符说明1、lstrip()方法用于截掉字符串左边的空格或指定的字符。语法str.lstrip([chars])2、参数分为str、chars。str:原...详情>>
2023-11-14 07:58:15python删除文档的方法
python中删除文档的方法1、delete_one()方法删除文档。delete_one()需要一个查询对象参数。它只删除了第一次出现。2、在删除大量文档时,使用de...详情>>
2023-11-14 06:54:49