最全总结:把模块当做脚本来执行的 7 种案例及其原理

点击上方“Python爬虫与数据挖掘”,进行关注

回复“书籍”即可获赠Python从入门到进阶共10本电子书

乱我心者,今日之日多烦忧。

本篇选自 Python黑魔法指南 -> 第二章 -> 第14节

github仓库: https://github.com/iswbm/magic-python

如本文对你有用,可否到 github 上帮我点个 star 呢?


1. 用法举例

前面的文章里其实分享过不少类似的用法。比如:

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)))'

 2. 原理剖析

上面的诸多命令,都有一个特点,在命令中都含有 -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> 的方式执行,只要在 package 下写一个 __main__.py 的文件即可。

  • 第二种:以 -m <package.module> 的方式执行,只要在 module 的代码中,定义一个 main 函数,然后在最外层写入下面这段固定的代码

if __name__ == '__main__':
    main()

上面我将 -m 的使用情况分为两种,但是实际上,只有一种,对于第一种,你完全可以将 -m <package> 理解为 -m <package.__main__> 的简写形式。

3. 实践一下

先把当前路径设置追加到 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

4. -m 存在的意义

-m 实现的效果,无异于直接执行一个 Python 模块/脚本。

那么问题就来了,那我直接执行不就行啦,何必多此一举再加个 -m 呢?

这个问题很有意思,值得一提。

当我们使用一个模块的时候,往往只需要记住模块名,然后使用 import 去导入它就行了。

之所以能这么便利,这得益于 Python 完善的导入机制,你完全不需要知道这个模块文件存在哪个目录下,它的绝对路径是什么?因为 Python 的包导入机制会帮你做这些事情。

换句话说,如果你不使用 -m 的方式,当你要使用 python -m json.tool,你就得这样子写

$ echo '{"name": "MING"}' | python /usr/lib64/python2.7/json/tool.py
{
    "name": "MING"
}

如此一对比,哪个更方便?你心里应该有数了。

------------------- End -------------------

往期精彩文章推荐:

欢迎大家点赞,留言,转发,转载,感谢大家的相伴与支持

想加入Python学习群请在后台回复【入群

万水千山总是情,点个【在看】行不行

/今日留言主题/

随便说一两句吧~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值