最近在看 __main__ 的官方文档 —— https://docs.python.org/3/library/__main__.html#module-__main__,提到一个 python -m 的用法,很是不理解,所以查找了很多文档,并进行了如下总结。
查看 Python 的 help 内容
![90c715077e2845a9fad7d10378ab641a.png](https://img-blog.csdnimg.cn/img_convert/90c715077e2845a9fad7d10378ab641a.png)
有无 -m 参数的比较
- python script.py # 直接执行脚本
- python -m script.py # 当做模块的方式执行,相当于 import
一般情况下,我们会想当然的认为,有无参数 -m 对程序会有不同的影响,但是很可惜,第二种写法是会在程序执行之后报错的。其正确的写法是:丢掉 .py 后缀。
首先直观的观察执行结果,Python 的版本是 3.6.3。 编写 script.py 脚本,内容如下:
![bde6c9181650ef4556f3a0d8948c129d.png](https://img-blog.csdnimg.cn/img_convert/bde6c9181650ef4556f3a0d8948c129d.png)
直接执行脚本
![9ca661b9d87ed868559bff6d8b8c4352.png](https://img-blog.csdnimg.cn/img_convert/9ca661b9d87ed868559bff6d8b8c4352.png)
当做模块方式执行
![28feacaf003475a2e1ce5354437ed1a5.png](https://img-blog.csdnimg.cn/img_convert/28feacaf003475a2e1ce5354437ed1a5.png)
显示的内容还有很多,只突出显示出了不同的地方。
通过比较不同的地方,我们发现:
第一种方法——直接运行脚本,当前脚本所在的路径会加入到 sys.path 列表中,但是 sys.modules 字典中的 __main__ 的路径不是绝对路径,只是脚本名称。
第二种方法——当做模块方式运行,当前脚本所在的路径不会加入到 sys.path 列表中,但是 sys.modules 字典中的 __main__的路径是绝对路径,同时,还引入了 runpy 和 pkgutil 两个模块。
runpy 的用途:定位并执行该模块。主要用途在于实现命令行 -m 执行 python 模块的效果。
pkgutil 的用途:获取包里面的所有模块列表。pkgutil.get_data() 可读取包内任何文件内容。
模块的导入机制
其实,上面的内容涉及到了 Python 包模块的导入机制。
要理解模块的导入机制,得理解几个关键的名词。sys.path -> sys.modules -> < module >.__dict__。
sys.path:是一个列表。保存着模块的搜索路径。如果路径没有存在与该列表中,可使用 sys.path.append() 导入。
sys.modules: 是一个字典。所有加载到内存中的模块都存放在该字典中。当 import 一个模块的时候,首先会在这个字典中查找是否已经加载了目标模块。如果已加载,则将模块的名字加入到正在调用 import 的模块的 Local 命名空间(也就是< module >.__dict__)中。如果没有,则从 sys.path 查找,找到后载入内存,并加入到 sys.modules 字典,名称也将导入到当前模块的 Local 命名空间。
藕丝空间——编程,我们是认真的!