“使用‘-m’选项将库模块作为脚本运行”是什么意思?

95

我是Python的新手(也是编程的新手),虽然有很好的文档,但我仍然无法理解-m指令的确切含义(特别是在创建虚拟环境时:python3 -m venv my_env)。

从文档中可以看出,它代表“将库模块作为脚本运行”:实际上,我无法理解这个概念以及运行命令时没有使用-m的区别。

此外,这是Python 3的一个特性吗?


3
文档是你的朋友:https://docs.python.org/3.5/using/cmdline.html#cmdoption-m - freakish
1
你读过文档了吗?只是问一下,因为你说它有很好的文档,但没有链接到“文档”。 - MSeifert
2个回答

153

Python模块只是位于Python能够找到的位置的脚本文件。与所有脚本一样,如果您知道它们的位置,可以直接运行它们,例如:python /path/to/module.py

正确设计的模块通常除了设置需要导入的功能和类型之外,不会有任何可见的副作用。这就是为什么您可以执行 import sys,但没有任何反应。

然而,有些模块在从命令行运行时可能会提供有用的内容。例如,venvhttp.serveridlelib:所有这些都是常规模块,可以从其他模块中导入而不会产生副作用。

但是,当直接执行时,它们都会执行一些任务(例如,venv设置虚拟环境,http.server运行简单的HTTP服务器,idlelib运行IDLE)。通常使用以下检查完成:

if __name__ == '__main__':
    print('Module is being executed directly, so do stuff here')

这是一种特殊的方式,用于识别脚本/模块是直接执行还是从其他模块导入。您可以在“What does if __name__ == '__main__': do?”了解更多相关问题。

因此,您可以像之前建立的那样使用python /path/to/module.py直接运行模块。但是,这需要您知道模块的完整路径。这就是-m选项发挥作用的地方:对于通常可以使用import modulename导入的模块,您可以使用python -m modulename直接运行该模块。就像您键入它的完整路径一样。

因此,对于上述示例,我们只需使用python -m venvpython -m http.serverpython -m idlelib即可。


12
另一个很棒的例子是使用 json.tool 在shell中实现漂亮打印。可通过以下命令实现:echo '{"1":"a","2":"b"}' | python -m json.tool - Sergej Schelle
4
很棒的回答。只有一个补充:如果这是一个“包”(一个目录而不是单个的 .py 文件),python -m 模块名 的工作方式与 python /路径/到/包 稍有不同。前者执行 __init__.py__main__.py,但后者仅执行 只有 __main__.py(更多细节) - starriet

0

这不是Python3的属性。在模块化脚本的情况下,您需要使用-m。例如,假设您有以下文件夹结构

|-HelloModule
  |_ __init__.py
  |_ hellomodule.py
|_ first_script.py

现在,如果您正在hellomodule.py中使用first_script.py的任何类、函数或对象,则必须将hellomodule.py作为模块运行,这意味着命令将更改为

python -m HelloModule/hellomodule

并且您必须从HelloModule目录外运行此命令。


1
对我来说,如果我们接受只有-m标志所做的就是上面答案中指定的内容,这看起来有点不对。导入一个函数与脚本无关,就好像它是从根目录运行的一样。 - Michael Heidelberg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接