作者 | 写代码的明哥
来源 | Python编程时光(ID:Cool-Python)
前面的文章里其实分享过不少类似的用法。比如:
1、 快速搭建一个 HTTP 服务
# python2
$ python -m SimpleHTTPServer 8888
# python3
$ python3 -m http.server 8888
效果如下:
2、快速构建 HTML 帮助文档
$ python -m pydoc -p 5200
效果如下:
3、快速进入 pdb 调试模式
$ python -m pdb demo.py
4、最优雅且正确的包安装方法
$ python3 -m pip install requests
5、快速美化 JSON 字符串
$ echo '{"name": "MING"}' | python -m json.tool
6、快速打印包的搜索路径
$ python -m site
效果如下:
7、用于快速计算程序执行时长
$ python3 -m timeit '"-".join(map(str, range(100)))'
上面的诸多命令,都有一个特点,在命令中都含有 -m 参数选项,而参数的值,SimpleHTTPServer, http.server, pydoc,pdb,pip, json.tool,site ,timeit 这些都是模块或者包。
通常来说模块或者包,都是用作工具包由其他模块导入使用,而很少直接使用命令来执行(脚本除外)。
Python 给我们提供了一种方法,可以让我们将模块里的部分功能抽取出来,直接用于命令行式的调用。效果就是前面你所看到的。
那这是如何实现的呢?
最好的学习方式,莫过于模仿,直接以 pip 和 json 模块为学习对象,看看目录结构和代码都有什么特点。
先看一下 pip 的源码目录,发现在其下有一个 __main__.py 的文件,难道这是 -m 的入口?
再看一下 json.tool 的源码文件,json 库下面却没有 __main__.py 的文件。
这就很奇怪了。
不对,再回过头看,我们调用的不是 json 库,而是 json 库下的 tool 模块。
查看 tool 模块的源代码,有一个名为 main 的函数:
但它这不是关键,main 函数是在模块中直接被调用的。
只有当 __name__ 为 __main___ 时,main 函数才会被调用。
if __name__ == '__main__':
main()
当模块被导入时,__name__ 的值为模块名,
而当模块被直接执行,__name__ 的值就变成了 __main__。
这下思路清晰了,我来总结一下:
想要使用 -m 的方式执行模块,有两种方式:
第一种:以 -m 的方式执行,只要在 package 下写一个 __main__.py 的文件即可。
第二种:以 -m 的方式执行,只要在 module 的代码中,定义一个 main 函数,然后在最外层写入下面这段固定的代码:
if __name__ == '__main__':
main()
上面我将 -m 的使用情况分为两种,但是实际上,只有一种,对于第一种,你完全可以将 -m 理解为 -m 的简写形式。
先把当前路径设置追加到 PATH 的环境变量中:
$ export PATH=${PATH}:`pwd`
先来验证一下第一种方法。
然后在当前目录下新建一个 demo 文件夹,并且在 demo 目录下新建一个 __main__.py 的文件,随便打印点东西。
# __main__.py
print("hello, world")
然后直接执行如下命令,立马就能看到效果。
$ python3 -m demo
hello,world
执行过程如下:
再来验证一下使用第二种方法。
在 demo 目录下再新建一个 foobar.py 文件:
# foobar.py
def main():
print("hello, world")
if __name__ == "__main__":
main()
最后执行一下如下命令,输出与预期相符。
$ python3 -m demo.foobar
hello, foobar
-m 实现的效果,无异于直接执行一个 Python 模块/脚本。
那么问题就来了,那我直接执行不就行啦,何必多此一举再加个 -m 呢?
这个问题很有意思,值得一提。
当我们使用一个模块的时候,往往只需要记住模块名,然后使用 import 去导入它就行了。
之所以能这么便利,这得益于 Python 完善的导入机制,你完全不需要知道这个模块文件存在哪个目录下,它的绝对路径是什么?因为 Python 的包导入机制会帮你做这些事情。
换句话说,如果你不使用 -m 的方式,当你要使用 python -m json.tool,你就得这样子写
$ echo '{"name": "MING"}' | python /usr/lib64/python2.7/json/tool.py
{
"name": "MING"
}
如此一对比,哪个更方便?你心里应该有数了。
更多精彩推荐
☞连按 5 次 Shift 重改 CMD 和密码并重启电脑,这个漏洞你不能不知道!
☞如何判断领导是在培养你,还是压榨你?看这4点就够了
☞微信iOS版朋友圈可删除评论;华为回应安卓系统断供;银河麒麟操作系统V10发布| 极客头条
☞万字长文总结机器学习的模型评估与调参 | 附代码下载
☞什么?一个核同时执行两个线程?
☞交易平台搅局者“Uniswap之父”,不会编程的“失业青年”,出手即巅峰
点分享点点赞点在看