python -m 与 python 不同之处

本文主要讨论这两种命令在执行.py文件时的不同之处

文件结构

(base) t@t-virtual-machine:~/桌面/source$ tree
.
├── ab.py
├── DirA
└── DirB
    └── b.py

2 directories, 2 files

解说:

  • 当前系统Linux-ubuntu,当前终端所在文件夹source

  • source文件夹内,包括2个文件夹(DirA, DirB),1个.py文件(ab.py)

  • 文件夹DirA内部无文件,文件夹DirB内部有一个.py文件(b.py)

代码内容

# ab.py
import sys
import DirB.b
print("ab.py 开始执行...")
print("__name__:",__name__)
print()
print("系统路径(sys.path):")
print('\n'.join(sys.path))
print()
if __name__ == "__main__":
print("source/ab.py")
# b.py
import sys
print("b.py 开始执行...")
print("__name__:",__name__)
print()
print("系统路径(sys.path):")
print('\n'.join(sys.path))
print()
if __name__ == "__main__":
print("source/DirB/b.py")

1 语法不同

python xxx.py 或者 python ./directory/xxx.py
python –m xxx 或者 python –m directory.xxx

执行代码 ①

(base) t@t-virtual-machine:~/桌面/source$ python ab.py

执行结果 ①

b.py 开始执行...
__name__: DirB.b #注意此行name的输出值(b.py是import的模块)
系统路径(sys.path):
/home/t/桌面/source
/home/t/anaconda3/lib/python39.zip
/home/t/anaconda3/lib/python3.9
/home/t/anaconda3/lib/python3.9/lib-dynload
/home/t/anaconda3/lib/python3.9/site-packages
ab.py 开始执行...
__name__: __main__ #注意此行name的输出值(直接执行的是ab.py)
系统路径(sys.path):
/home/t/桌面/source
/home/t/anaconda3/lib/python39.zip
/home/t/anaconda3/lib/python3.9
/home/t/anaconda3/lib/python3.9/lib-dynload
/home/t/anaconda3/lib/python3.9/site-packages
source/ab.py #这个结果会被输出,证明当前程序执行时,进入了ab.py的__main__函数

执行代码 ②

(base) t@t-virtual-machine:~/桌面/source$ python -m ab

执行结果 ② (= 执行结果①)

b.py 开始执行...
__name__: DirB.b #注意此行name的输出值
系统路径(sys.path):
/home/t/桌面/source
/home/t/anaconda3/lib/python39.zip
/home/t/anaconda3/lib/python3.9
/home/t/anaconda3/lib/python3.9/lib-dynload
/home/t/anaconda3/lib/python3.9/site-packages
ab.py 开始执行...
__name__: __main__ #注意此行name的输出值
系统路径(sys.path):
/home/t/桌面/source
/home/t/anaconda3/lib/python39.zip
/home/t/anaconda3/lib/python3.9
/home/t/anaconda3/lib/python3.9/lib-dynload
/home/t/anaconda3/lib/python3.9/site-packages
source/ab.py #这个结果会被输出,证明当前程序执行时,进入了ab.py的__main__函数

执行代码 ③

(base) t@t-virtual-machine:~/桌面/source$ python ./DirB/b.py

执行结果 ③

b.py 开始执行...
__name__: __main__ #注意此行name的输出值(这个时候直接执行的是b.py)
系统路径(sys.path):
/home/t/桌面/source/DirB
/home/t/anaconda3/lib/python39.zip
/home/t/anaconda3/lib/python3.9
/home/t/anaconda3/lib/python3.9/lib-dynload
/home/t/anaconda3/lib/python3.9/site-packages
source/DirB/b.py #这个结果会被输出,证明当前程序执行时,进入的是b.py的__main__函数

执行代码 ④

(base) t@t-virtual-machine:~/桌面/source$ python -m DirB.b

执行结果 ④ (= 执行结果 ③)

b.py 开始执行...
__name__: __main__ #注意此行name的输出值
系统路径(sys.path):
/home/t/桌面/source
/home/t/anaconda3/lib/python39.zip
/home/t/anaconda3/lib/python3.9
/home/t/anaconda3/lib/python3.9/lib-dynload
/home/t/anaconda3/lib/python3.9/site-packages
source/DirB/b.py #这个结果会被输出,证明当前程序执行时,进入的是b.py的__main__函数

总结

  1. 直接执行.py文件

    • python xxx.py 可以直接执行.py文件,而python -m xxx 执行时不加.py后缀!

  2. 执行多级目录下的.py文件

    • python xxx.py 直接按照相对路径格式索引即可;

    • python -m xxx 需要按照import的格式进行路径索引


2 系统路径不同

  • 直接执行方式(python xxx.py 或者 python ./directory/xxx.py ):系统路径涵盖了脚本执行所在文件夹

  • 模块执行方式(python –m xxx 或者 python –m directory.xxx):类似import导入工具包的语法,系统路径只包含命令执行时的当前路径

执行代码 ⑤

(base) t@t-virtual-machine:~/桌面/source$ python
Python 3.9.2 (default, Mar  3 2021, 20:02:32) 
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ab

执行结果 ⑤

b.py 开始执行...
__name__: DirB.b #注意此行name的输出值
系统路径(sys.path):
/home/t/anaconda3/lib/python39.zip
/home/t/anaconda3/lib/python3.9
/home/t/anaconda3/lib/python3.9/lib-dynload
/home/t/anaconda3/lib/python3.9/site-packages
ab.py 开始执行...
__name__: ab #注意此行name的输出值
系统路径(sys.path):
/home/t/anaconda3/lib/python39.zip
/home/t/anaconda3/lib/python3.9
/home/t/anaconda3/lib/python3.9/lib-dynload
/home/t/anaconda3/lib/python3.9/site-packages

解释 执行代码⑤的结果,原因在于,此时的主程序是python解释器,ab.py 和 b.py都是其模块/子模块


3 __name__ 输出值不同

从(执行结果①)python ab.py & (执行结果③)python ./DirB/b.py可观察得到:

import的是模块名
直接执行哪一个,哪一个的__name__就是main

从执行代码⑤可以看出,import导入模块时,__name__都不是main


总结

  1. 语法不同

  2. 执行过程,系统路径不同(并不是执行过后改变了路径)

  3. 特别重要:__name__的输出值会有不同


参考资料: