python -m标志的含义

rwqw0loc  于 2022-12-15  发布在  Python
关注(0)|答案(8)|浏览(273)

python -m pip install <package>中的-m是什么意思?或者在使用python -m pip install --upgrade pip升级pip时。仅运行“pip install“时有什么区别

t9aqgxwy

t9aqgxwy1#

请考虑以下场景。
您安装了三个版本的Python:

  • Python 3.7语言
  • Python 3.8语言
  • Python 3.9

你的“默认”版本是3.8,它是出现在你的 path 中的第一个版本,因此,当你在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激活了虚拟环境,在shell中输入python将启动Python 3.9解释器。

但是,如果您键入

pip install <some-package>

那么pip使用的是什么版本?是默认版本的pip,即Python 3.8,还是虚拟环境中的Python版本?
避免这种模糊性的一个简单方法就是使用

python -m pip install <some-package>

-m标志确保您使用的是绑定到活动Python可执行文件的pip。
始终使用-m是一个很好的实践,即使您只安装了一个全局版本的Python来创建虚拟环境。

参考路径

所谓的 path 是系统搜索可执行文件的目录列表,当你键入一个命令,比如python,这个列表会从第一个目录遍历到最后一个目录,搜索与你键入的命令相匹配的文件名。
如果找到文件名/命令,则执行匹配的文件,而不考虑以后可能的匹配。如果没有匹配,则获得Command not found或其变体。此行为是设计的。
在UNIX系统上,路径环境变量称为$PATH,而在Windows系统上则称为%PATH%

关于-m-flag的更多一般性注解(2022年12月)

大多数人看到这篇文章可能会想知道上面pip的解释,但从更普遍的意义上讲,当使用python -m some_module时,-m标志会使Python将some_module作为脚本执行,这在docs中有说明,但如果没有一些基本知识,可能很难理解。

“作为脚本运行”是什么意思?

在Python中,模块some_module通常被导入到另一个Python文件中,并且在导入文件的顶部有一个import some_module语句。这样就可以在导入文件中使用some_module中定义的函数、类和变量。要将some_module作为脚本执行而不是导入它,您将在文件中定义一个if __name__ == "__main__"块。在命令行上运行python some_module.py时,将执行此块。这很有用,因为您希望在导入到其他文件时运行此代码块,但您确实希望它在从命令行调用时运行。
对于项目内部的模块,这个脚本/模块构造应该按原样运行,因为Python在从终端运行时会从工作目录中找到模块:

python some_module.py

但是对于Python标准库中的模块来说,这是行不通的,Python文档中的例子使用了timeitpip的工作原理是一样的):

python3 timeit -s 'print("hello")'  # 'python timeit.py ...' fails as well

这将返回错误:"python: can't open file '/home/<username>/timeit': [Errno 2] No such file or directory"
添加-m标志告诉Python在path中查找timeit.py,并从文件中执行if __name__ == "__main__"子句。

python3 -m timeit -s 'print("hello")'

这按预期工作。
timeit模块的if __name__ == "__main__"块的源代码可以在here中找到。

8ulbf1ek

8ulbf1ek2#

来自Python文档:
因为参数是一个模块名,所以不能给予文件扩展名(.py)。module-name应该是一个有效的Python模块名,但是实现可能并不总是强制这样(例如,它可能允许你使用一个包含连字符的名称)。
包名也是允许的。当提供包名而不是正常的模块时,解释器会将<pkg>.__main__作为主模块执行。这种行为有意类似于作为脚本参数传递给解释器的目录和zip文件的处理。

eblbsuwk

eblbsuwk3#

-m代表module-name
Command line and environment开始:
python [-bBdEhiIOqsSuvVWx?] [-c命令|-m模块名称|脚本|- ] [参数]

0ve6wy6x

0ve6wy6x4#

如果您键入python --help
你得到

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

如果您使用command --helpman command,终端中的许多内容将向您展示如何使用它

fykwrbwg

fykwrbwg5#

-m与命令行上的python语句一起使用,后跟<module_name>时,它使模块能够作为可执行文件执行。
您可以参考python文档以获得相同的信息,或者运行python --help

yb3bgrhw

yb3bgrhw6#

这其实是一个很有趣的问题,所以让我们来探讨一下顶部评论中@jedwards链接的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进一步扩展了这种行为。
提出的语义相当简单[原文如此]:如果使用-m来执行模块,则在根据顶层模块的语义执行模块之前,使用PEP 302导入机制来定位模块并检索其编译代码。
它进一步解释了python将识别模块来自哪个包,使用标准过程导入那个包,然后运行模块.据我所知,调用“python3 -m package.module”与调用:

python3
from package import module

-m标志将以__file__而不是__main__的身份运行模块。它还将本地目录插入sys.path而不是脚本目录。因此,它中断了相对导入,尽管这不是有意的。因此,作者建议始终使用绝对导入,这也取决于您如何调用它--“python3 -m package.module”与“python3 -m模块”。

**理论上很简单--它加载python并导入模块,而不是将代码转储到__main__中。**实际上,这有很多影响。这是一个不同的导入系统,行为也不同。其中一些更改不是故意的,只是在实现后才发现。Python的导入很混乱,混淆是正常的。

t3irkdon

t3irkdon7#

令人惊讶的是,这是如此难以回答,当有些人说,这个问题太简单,麻烦。
据我所知,实际用途是当您不在目录中时,可以使用点标记来运行脚本。
您可以运行python -m path.to.my.happy.place
而不是在path/to/my/happy中运行python place.py

u1ehiz5o

u1ehiz5o8#

如果你安装了多个版本的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

相关问题