诺志
软硬件开发技术笔记
Python -m 选项的作用
2017-01-24

在运行pip安装软件的时候,有些文档的写法如下

# python -m pip install xxx

看下python的帮助文档

# main python

-m module-name
    Searches sys.path for the named module and runs the corresponding .py file as a script.

直译过来就是以脚本的方式运行模块的相应py文件, 但是通过测试发现,大部分模块是不能这么玩的,比如:

# python -m urllib3
/usr/bin/python: No module named urllib3.__main__; 'urllib3' is a package and cannot be directly executed
# python -m yum
/usr/bin/python: No module named yum.__main__; 'yum' is a package and cannot be directly executed
# python -m werkzeug
/usr/bin/python: No module named werkzeug.__main__; 'werkzeug' is a package and cannot be directly executed
# python -m flask
/usr/bin/python: No module named flask.__main__; 'flask' is a package and cannot be directly executed

那为什么pip能用python -m执行? 为此我来实现一个可以用python -m执行的模块

1.先按正常方式定义一个model模块, 里面只有一个do.py文件, 执行具体的函数; test.py为调用这个模块的测试程序

# tree 
.
|-- model
|   |-- do.py
|   `-- __init__.py
`-- test.py
# file: do.py
def echo(v):
    print "get:%s" % v
# file: __init__.py
# __init__.py只是一个空文件,告诉python 把model当一个模块来处理
# file: test.py
import sys
from model import do 

if __name__ == "__main__":
    if len(sys.argv) < 2:
        sys.exit(1)
    do.echo(sys.argv[1])

执行效果就是直接显示传入的参数

# python test.py xxx
get:xxx

但这个时候,我们使用-m选项还是不能执行的, 我们需要进行第二步

# python -m model xxx
/usr/bin/python: No module named model.__main__; 'model' is a package and cannot be directly executed

2.在model下创建一个__main__.py文件, 发现这个文件的内容和上面的test.py的文件差不多,

# tree
.
`-- model
    |-- do.py
    |-- __init__.py
    `-- __main__.py
# file: __main__.py
import sys
import do

if __name__ == "__main__":
    if len(sys.argv) < 2:
        sys.exit(1)
    do.echo(sys.argv[1])

这个时候,我们再使用-m选项,发现已经可以正常执行了

# python -m model xxx
get:xxx

所以: 其实python -m在执行的时候,会到sys.path下寻找这个模块, 然后在这个模块下执行__main__.py

再来回头看看pip, 它能直接python -m pip执行,是因为pip也有这个__main__.py文件

# rpm -ql python2-pip | grep __main__.py
/usr/lib/python2.7/site-packages/pip/__main__.py
/usr/lib/python2.7/site-packages/pip/__main__.pyc
/usr/lib/python2.7/site-packages/pip/__main__.pyo

有兴趣的同学可以对比下__main__.py/usr/bin/pip的内容,其实是一样的

# cat /usr/bin/pip
# cat /usr/lib/python2.7/site-packages/pip/__main__.py

问题 : 既然pip install xxx能用,-m pip install xxx也能用,为啥需要第二种复杂又难理解的方式呢???

分类
2篇
c
1篇
8篇
18篇
8篇
2篇
搜索