是否使用 -m 选项执行 Python 代码
使用-m 标志。
当你有一个脚本时,结果几乎是一样的,但是当你开发一个包时,如果没有 -m 标志,如果你想在其中运行一个子包或模块,就没有办法让导入正常工作将包作为程序的主要入口点(相信我,我已经尝试过了。)
文档
喜欢docs on the -m flag 说:
在 sys.path 中搜索命名模块并将其内容作为__main__ 模块执行。
和
与 -c 选项一样,当前目录将添加到 sys.path 的开头。
所以
python -m pdb
大致相当于
python /usr/lib/python3.5/pdb.py
(假设您的当前目录中没有名为 pdb.py 的包或脚本)
解释:
行为“故意类似于”脚本。
许多标准库模块包含在执行时作为脚本调用的代码。一个例子是timeit module:
一些python代码打算是run as a module:(我觉得这个例子比命令行选项doc例子好)
$ python -m timeit '"-".join(str(n) for n in range(100))'
10000 loops, best of 3: 40.3 usec per loop
$ python -m timeit '"-".join([str(n) for n in range(100)])'
10000 loops, best of 3: 33.4 usec per loop
$ python -m timeit '"-".join(map(str, range(100)))'
10000 loops, best of 3: 25.2 usec per loop
And from the release note highlights for Python 2.4:
-m 命令行选项 - python -m modulename 将查找模块
在标准库中,并调用它。例如,python -m pdb
相当于python /usr/lib/python2.4/pdb.py
后续问题
此外,David Beazley 的 Python Essential Reference 将其解释为“The
-m 选项将库模块作为脚本运行,该脚本在执行主脚本之前在 __main__ 模块内执行”。
这意味着您可以使用 import 语句查找的任何模块都可以作为程序的入口点运行 - 如果它有一个代码块,通常接近结尾,if __name__ == '__main__':。
-m不添加当前目录到路径:
其他地方的评论说:
-m 选项也将当前目录添加到 sys.path 中,这显然是一个安全问题(参见:预加载攻击)。这种行为类似于 Windows 中的库搜索顺序(在它最近被强化之前)。遗憾的是 Python 没有跟上潮流,也没有提供简单的方法来禁用添加 .到 sys.path
好吧,这证明了可能的问题 - (在 Windows 中删除引号):
echo "import sys; print(sys.version)" > pdb.py
python -m pdb
3.5.2 |Anaconda 4.1.1 (64-bit)| (default, Jul 5 2016, 11:41:13) [MSC v.1900 64 bit (AMD64)]
使用-I 标志将其锁定以用于生产环境(3.4 版中的新功能):
python -Im pdb
usage: pdb.py [-c command] ... pyfile [arg] ...
etc...
来自the docs:
-I
以隔离模式运行 Python。这也意味着 -E 和 -s。在隔离模式下,sys.path 既不包含脚本的目录,也不包含用户的站点包目录。所有 PYTHON* 环境变量也会被忽略。可能会施加更多限制以防止用户注入恶意代码。
__package__ 是做什么的?
它启用了显式的相对导入,但与这个问题并不特别相关 - 请在此处查看此答案:What's the purpose of the "__package__" attribute in Python?