您的位置:首页 > 编程语言 > Python开发

【Python学习手册】Python模块知识总结

2017-05-16 09:40 651 查看

导入模块(import)执行过程

1.找到模块文件
2.编译成位码(如果发现字节码文件比源文件的时间旧,即修改过源文件,那么就会对源文件进行重新编译,如果在标准模块搜索库中,只发现了字节码文件,程序就会直接加载字节码)
3.执行模块的代码来创建模块中定义的对象(执行字码,从上到下依次执行载入模块中的命令)。
这三个步骤只在程序执行时,模块第一次导入才会进行。如果多次导入,只是提取了内存中已加载的对象。从技术上讲,python在加载模块时,会把模块存入一个名为sys.modules的表中,并在执行导入时,对表中的内容进行查找,如果不存在就会导入,开始执行以上三个步骤。
注:导入的模块才会在生成字节码,对于直接运行的顶层的python程序是不会出现.pyc字节码的,除非这个文件被其他模块导入过,顶层文件的字节码在内存中使用后就直接被丢弃了。

模块搜索路径规则

1.程序的主目录(执行python模块时,用户所在的当前目录)
2.PYTHONPATH环境变量目录(类似环境变量,如PYTHONPATH=/home/Python/lib,优先级从左至右搜索)
3.标准链接库目录
4.任何.pth文件的内容,必须是以.pth为后缀的文件且文件内容中的目录要真实存在的才会被正常导入(如果存在的话。这种方式是python中比较新的模块路径规则,可以作为PYTHONPATH的一种替代方式,而路径文件在不同的系统和python版本中,存放的位置都不一样,一个以Python N.M发布的Python版本,在Windows系统上在C:\PythonNM和C:\PythonNM\Lib\site-packages中查找路径文件,在UNIX和Linux上则在/usr/local/lib/pythonN.M/site-packages
/usr/local/lib/site-python, 经过试验'/usr/local/lib/python3.4/dist-packages 这个目录下也是有效的。)
这四个组件组合起来变成了sys.path,第1和3是自动定义的,2和4是用户定义,可以用于自己项目扩展路径。

实际上,import 和 from语句都是赋值语句:
1.import将整个模块对象赋值给一个变量名。
2.from将一个或者多个变量名赋值给模块中同名的变量中。
from语句可能导致导入变量时,覆盖本模块中已经存在的变量,导致混乱和缺陷。在使用时,只要注意到这一点,from语句可以为程序员省掉很多麻烦。
内部模块命名空间是作为字典对象进行储存的,它们只是普通的字典对象。可以通过__dict__方法来获取模块命名空间字典,在模块中赋值的变量名都成为了字典的键。
>>> import string
>>> list(string.__dict__)
['ascii_uppercase', '__spec__', '__cached__', '__name__', 'punctuation', 'ChainMap', 'ascii_lowercase', 'whitespace', '_re', '__builtins__', '_string', 'ascii_letters', 'capwords', 'octdigits', 'Template', '_TemplateMetaclass', '__doc__', 'printable', '__file__', '__loader__', 'hexdigits', 'digits', 'Formatter', '__package__']
>>>


导入操作不会赋予被导入文件中的代码对上层代码的可见度:被导入文件无法看见进行导入的文件内的变量名,更确切的说:

1.函数觉得无法看见其它函数内的变量名,除非它们从物理上处于这个函数内。
2.函数程序代码绝对无法看见其它模块内的变量名称,除非执行了明确的导入。
确切的说,模块的嵌套无法实现向顶层(上层)的嵌套,但是有可能向下进行深入的嵌套。

模块重载

1.import导入只会在模块中第一次导入时,加载并执行模块中的代码。
2.在之后的导入,都是使用已经加载的模块,并不会重新执行模块
3.如果要重新加载已经加载过的模块,使用reload内置函数。
reload与import不同的是:
1.reload是python中的内置函数,而不是语句。
2.传给reload的是已经存在的模块对象,而不是变量名
3.reload在python3.0中位于模块之中,必须导入才能使用。from imp import reload
reload时会重新执行模块中顶层文件的内容,但reload并不会删除并重建模块对象,而是在适当的地方修改模块对象。reload函数并不会加载模块中更深层的模块,即只加载顶层的代码。
reload注意事项:

reload会在模块当前命名空间内执行模块文件的新代码。
1.文件顶层赋值语句会使得变量名换成新值。
2.重载会影响所有使用import读取了模块的客户端。
3.重载只会对以后使用from的客户端造成影响。
写个文件来实验一下上面规则:
我们有一个文件modul1.py:
test="No modified"
只写了这一个代码
在程序中导入这个模块:
>>>import modul1
>>> test
'No modified'
>>> from modul1 import *
>>> modul1.test
'No modified'
以上看到两种test,一个是直接通过from语句赋值得到的test,而另一种是通过模块调用(import语句)得到的modul1.test。修改modul1.py文件后,再继续执行reload语句:
>>> from imp import reload
>>> reload(modul1)
<module 'modul1' from '/home/*****/work/Python/Python_Practise/modul1.py'>
>>> test
'No modified'
>>> modul1.test
'have been modified'
>>> from modul import *
>>> test
'have been modified'


验证了规则2,3的同时,我们也可以想到from语句实际上是对变量的赋值,而import语句是对模块的引用。reload语句实际上只是修改了模块,重载了模块,而没有直接修改通过from语句得到的变量,当再次执行from语句时,即更新了本地作用中的变量。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: