Python-m 标志的含义

python -m pip install <package>中-m 是什么意思? 或者在使用 python -m pip install --upgrade pip升级 pip 的时候

90845 次浏览

如果你输入 python --help

你得到了

// More flags above
-m mod : run library module as a script (terminates option list)
// and more flags below

如果你使用 command --help或者 man command,终端中的很多东西都会告诉你如何使用它

-m代表 module-name

来自 命令行和环境:

Python [-bBdEhiIOqsSuvVWx? ][-c command |-m module-name | script |-][ args ]

来自 巨蟒文档:

因为参数是模块名,所以不能给出文件扩展名(。派)。module-name应该是一个有效的 Python 模块名称,但是实现可能并不总是强制这样做(例如,它可能允许您使用一个包含连字符的名称)。

包名也是允许的。当提供包名而不是普通模块时,解释器将执行 <pkg>.__main__作为主模块。这种行为有意类似于作为脚本参数传递给解释器的目录和 zipfiles 的处理。

-m与命令行上的 python语句一起使用,后跟 <module_name>语句时,它使模块能够作为可执行文件执行。

您可以参考 python docs 获得相同的信息,或者运行 python --help

如果已经安装了多个版本的 python,并且希望升级 pip pip install --upgrade pip,那么如何知道哪个 python 版本将受到影响?它取决于 shell 的路径变量。在这种情况下,您可能还会得到警告。为了避免这种混淆,使用 -m,然后在变量 Sys.path中查找。这是 -m的另一个优点。

# importing module
import sys
  

# printing all directories for
# interpreter to search
sys.path

考虑下面的场景。

您已经安装了三个版本的 Python:

  • Python 3.7
  • Python 3.8
  • Python 3.9

您的“默认”版本是3.8。这是第一个出现在你的 路径。因此,当您在 shell 中键入 python3(Linux 或 Mac)或 python(Windows)时,您将启动一个3.8解释器,因为这是在遍历您的路径时发现的第一个 Python 可执行文件。

假设您正在启动一个新项目,希望在其中使用 Python 3.9。您创建一个名为 .venv的虚拟环境并激活它。

python3.9 -m venv .venv         # "py -3.9" on Windows
source .venv/bin/activate    # ".venv\Scripts\activate" on Windows

现在,我们已经使用 Python 3.9激活了虚拟环境。

但是 ,如果你输入

pip install <some-package>

那么使用哪个版本的 pip呢?它是默认版本(即 Python 3.8)的 pip,还是虚拟环境中的 Python 版本?

避免这种歧义的一个简单方法就是使用

python -m pip install <some-package>

-m标志确保您正在使用绑定到活动 Python 可执行文件的 pip。

始终使用 -m是一个很好的实践,即使您只安装了一个全局版本的 Python,从中您可以创建虚拟环境。

路径

所谓的 路径是系统在其中搜索可执行文件的目录列表。当您键入命令(如 python)时,此列表将从第一个目录遍历到最后一个目录,搜索与您键入的命令相匹配的文件名。

如果找到文件名/命令,则执行匹配的文件,而不考虑以后可能发生的匹配。如果没有匹配发生,你得到一个 Command not found或其变化。这种行为是设计好的。

在 UNIX 系统中,路径环境变量被称为 $PATH,而在 Windows 系统中,路径路径被称为 %PATH%

这实际上是一个有趣的问题,所以让我们来探讨一下 顶级评论中@jedward 链接的 pep 338。

M 标志最初的用途比较简单——将模块名称转换为脚本名称。在 python 2.4中,行为是:

the command line is effectively reinterpreted from python <options> -m
<module> <args> to python <options> <filename> <args>.

这似乎没有什么用处,但这就是它当时的作用。 Pep 338进一步扩展了这种行为。

提出的语义相当简单[ sic ] : if-m 用于 执行模块,PEP 302导入机制用于定位 模块中执行模块之前,检索其已编译的代码 与顶级模块的语义相一致。

接下来进一步解释,python 将识别模块所来自的包,使用标准进程导入该包,并运行该模块。根据我的理解,“ python3-m package.module”与调用:

python3
from package import module

M 标志将作为 __file__而不是 __main__运行模块。它还将把本地目录插入 sys.path,而不是脚本的目录。因此,它打破了相对进口,虽然这不是故意的,因此作者建议始终使用绝对进口。它还取决于您如何调用它——“ python3-m package.module”与“ python3-m module”不同。

理论上它很简单——它加载 python 并导入模块,而不是将代码转储到 __main__中。在实践中有很多效果。这是一个行为不同的不同导入系统。其中一些更改并非有意为之,而是在实现之后才发现的。Python 的导入是一团糟,可以混淆。

当一些人说这个问题太简单以至于无法解决的时候,这个问题竟然如此难以回答。

据我所知,实际用途是当您不在目录中时,可以使用点符号来运行脚本。

你可以逃跑 python -m path.to.my.happy.place

而不是在 path/to/my/happy运行 python place.py