上一篇文章介绍了python代码的计时工具line_profiler,其可以计算每行代码的运行时间,十分之好用,但是最后的一小节有说到其在计时的同时还可以生成一个结果文件,若是有需要的话可以再使用python -m命令查看其结果。其命令使用方式如下:
python -m line_profiler test.py.lprof
由于个人比较好奇,我就多方查阅资料,但网上各位大佬的博客写的可能有点深奥,同时也并未清晰明了地展示其能达到功能,我还是花了好久才最终终于大概弄懂了这个-m的含义以及到底它有什么用。当然这可能也是因为我的理解能力较差,吼吼吼。
今天就简单解释一下python -m的含义啦。
我们平常在命令行中可能大都会使用python + 脚本名(例如python test.py)来运行脚本吧,这样其实就能看出来了python实际上就是一个命令或者说是一个软件,因此python也具有很多可用的参数,要查看这些参数可以在命令行使用python -h查看帮助文档即可。
在这个帮助文档中,可以看到对-m 的解释是:
-m mod : run library module as a script (terminates option list)
也就是将一个python library 中的模块当做脚本来运行。这里实际上可能理解能力强的人就已经能理解了,虽说理解了,但是将模块当做脚本运行有什么作用呢?
将模块当做脚本来运行,是因为一般情况下模块是通过import后,我们再使用模块中的各种函数或者功能的。但是正如之前的某篇文章说过的一样,在python脚本中一般会有一个如下的语句:
if __name__ == "__main__": # 这里不知道怎么打出来,只能在代码块里打了
main()
这个语句就是防止别人调用这个脚本中会直接运行main的内容,而单独运行此脚本时则可以运行main中的内容。
这里针对模块来说,模块一般是被通过import引入的,例如正则re,画图的turtle、还有site模块等。引入模块时只需要输入脚本前缀即可,不需要输入后缀.py。在python自带库中有很多模块是没有上面的if 语句的,也就是它们一般不会直接被执行(例如使用python re.py的情况),但某些库是带有这种语句的,例如site模块:
也就是在特定情况下我们可以将这个模块当做脚本来运行。这时候本文介绍的python -m参数就派上用场啦,python -m 表示我们把后面跟的参数当做是一个模块,运行结果也就像运行其它的python脚本一样,也会运行main中的内容,只不过这里就是特定的识别后续跟的是模块(因为是模块,所以直接写文件前缀即可)。
除上述的点外,python -m由于将后面跟的参数当做模块,因此其会到sys.path也就是python搜索所需模块的路径集去寻找对应的模块,这就有点类似系统的环境变量,当引入某个模块时,就会去到sys.path中寻找到这个模块并载入内存。sys.path是一个列表,可以自定义地增加路径。通过上面的介绍,总结一下也就是我们只要知道某个已有模块的模块名(即此模块已经被安装,例如通过pip安装的line_profiler),就可以使用python -m + 模块名 的方式执行这个模块脚本了,不需要输入模块脚本所处的绝对位置(前提是模块处于sys.path中哈)。
为了帮大家更好理解,看一下我的sys.path吧(可以放大看哈)!
# 这里site模块含有if __name__ == '__main__' 语句,其可以通过python -m执行,
# 但我也不知道有什么用哈,就演示一下
# site模块在我电脑上的绝对路径为
# C:\Users\MyPC\AppData\Local\Programs\Python\Python38\Lib\site.py
python -m site
# 在命令行执行,结果为:
'''
sys.path = [
'D:\\Backup\\桌面',
'C:\\ProgramData\\Anaconda3\\python38.zip',
'C:\\ProgramData\\Anaconda3\\DLLs',
'C:\\ProgramData\\Anaconda3\\lib',
'C:\\ProgramData\\Anaconda3',
'C:\\Users\\MyPC\\AppData\\Roaming\\Python\\Python38\\site-packages',
'C:\\ProgramData\\Anaconda3\\lib\\site-packages',
'C:\\ProgramData\\Anaconda3\\lib\\site-packages\\win32',
'C:\\ProgramData\\Anaconda3\\lib\\site-packages\\win32\\lib',
'C:\\ProgramData\\Anaconda3\\lib\\site-packages\\Pythonwin',
]
USER_BASE: 'C:\\Users\\MyPC\\AppData\\Roaming\\Python' (exists)
USER_SITE: 'C:\\Users\\MyPC\\AppData\\Roaming\\Python\\Python38\\site-packages' (exists)
ENABLE_USER_SITE: True
'''
其实对于除了python sys.path路径中的各种模块外,平常使用-m的机会可能还是不多,因为正常情况下使用-m和不使用-m的结果是一样的。
很多博文写的是通过使用python直接执行脚本和使用python -m来执行脚本产生的sys.path,但不知道为啥我执行后两个的sys.path相同,我就没有进一步去理解了。读者可以自己试试哈。
# 假设命名为test.py
import sys
print(sys.path)
print(sys.modules)
# 在命令行使用python -m test和python test.py的产生的sys.path结果相同。
# 产生的sys.modules的结果不同
python运行某脚本时所有加载到内存的模块都放在sys.modules中,使用python运行脚本和使用python -m两种方式不同的地方在于
可以看出后者被当做了模块,前者则是脚本中的main被当做了模块。
虽说使用机会少,但是看了网上博主们的博客后发现还是有可能用上的。举个例子就行啦:
比如我这里有一个test.py和一个文件夹123,文件夹中还有一个n.py
# test.py内容
# nothing
# n.py内容
import sys
import test
print(sys.path)
print(sys.modules)
python -m 123.n
# 这个命令是可以运行的,也就是123.n被当做了模块,这或许也是python各种库的
# 组成方式吧,不是很懂,先使用一下吧。在123文件夹中的n.py写上import test 可能大家觉得不太行,
# 但是实际上是可以的哦,这是因为sys.path在这种方式下是包含了上一级目录的,也就是包含123这个文件夹
# 和test.py这个文件的路径。大家可以多理解一下下!
# 这种使用点号的方式也不是很懂,以后再慢慢学习吧!
这种方式的使用使我们在需要导入某个脚本时不用一定要移动脚本,还是会有一定用处的哈。我觉得平常在自己的脚本中能使用的可能就是这种情况啦!不过实际上要达到这样的功能,可以直接在每个文件夹中加入一个额外的__init__.py,这样也可以解决问题的哦,这个部分了解不多,可以在网上看看其它内容哦!
实际上我也还有点不是很懂,先写下这些,哈哈,以后有更深的理解再把内容加上。
参考:与python -m命令有关的问题
参考:python sys.modules
参考:Python的-m参数