此问题已在此处有答案:
What's the difference between "pip install" and "python -m pip install"?(3个答案)
What is the purpose of the -m switch?(6个答案)
4天前关闭。
当我使用python -m pip install <package>
时,它与仅使用pip install <package>
有什么不同?同样,为什么要编写python -m pip install --upgrade pip
来升级Pip,而不是只写pip install --upgrade pip
?
8条答案
按热度按时间zpqajqem1#
考虑以下场景。
你安装了三个版本的Python:
您的“默认”版本是3.8。这是第一个出现在你的 * 路径 *。因此,当您在shell中键入
python3
(Linux或Mac)或python
(Windows)时,您将启动3.8解释器,因为这是遍历路径时找到的第一个Python可执行文件。假设你开始了一个新的项目,你想要使用Python 3.9。创建一个名为
.venv
的虚拟环境并激活它。我们现在已经使用Python 3.9激活了虚拟环境。在shell中输入
python
将启动3.9解释器。但是,如果你输入
pip
是什么版本?它是否是默认版本的pip,即Python 3.8,还是虚拟环境中的Python版本?一个简单的方法来解决这个模糊性是简单地使用
-m
标志确保您正在使用绑定到活动Python可执行文件的pip。最好始终使用
-m
,即使您只安装了一个用于创建虚拟环境的Python全局版本。回复路径
所谓的 path 是系统搜索可执行文件的目录列表。当您键入一个命令(如
python
)时,此列表将从第一个目录遍历到最后一个目录,搜索与您键入的命令匹配的文件名。如果找到文件名/命令,则执行匹配的文件,而不考虑以后可能的匹配。如果没有匹配,则得到
Command not found
或其变体。这种行为是设计出来的。在UNIX系统上,path环境变量称为
$PATH
,而在Windows系统上,它被称为%PATH%
更多关于
-m
-flag的一般注解(Dec. 2022年)大多数人看到这可能会希望上面给出的解释与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标准库中的模块,这将不起作用。Python文档中的示例使用
timeit
(pip
的工作原理相同):这将返回错误:
"python: can't open file '/home/<username>/timeit': [Errno 2] No such file or directory"
添加
-m
标志告诉Python在path中查找timeit.py
并从文件中执行if __name__ == "__main__"
子句。这和预期的一样。
timeit模块的
if __name__ == "__main__"
块的源代码可以在here中找到。798qvoo82#
Python Docs:
因为参数是一个模块名,所以不能给予文件扩展名(.py)。
module-name
应该是一个有效的Python模块名称,但实现可能并不总是强制执行此名称(例如它可能允许您使用包含连字符的名称)。包名称也是允许的。当提供了一个包名而不是一个普通的模块时,解释器将执行
<pkg>.__main__
作为主模块。这种行为有意类似于作为脚本参数传递给解释器的目录和zip文件的处理。u5rb5r593#
如果键入
python --help
你得到
如果您使用
command --help
或man command
,终端中的许多内容将向您展示如何使用它hgc7kmma4#
-m
代表module-name
。Command line and environment:
python [-bBdEhiIOqsSuvVWx?] [-c命令|-m模块名称|脚本|- ] [args]
92vpleto5#
当
-m
与命令行上的python
语句一起使用时,后跟<module_name>
,则它使模块能够作为可执行文件执行。您可以参考python文档,或者运行
python --help
eivgtgni6#
这实际上是一个有趣的问题,所以让我们在顶部评论中探索由@jedwards链接的pep 338。
-m标志最初用于一个更简单的用途-将模块名转换为脚本名。在Python 2.4中,行为是:
这看起来不是很有用,但这就是它当时所做的。Pep 338进一步扩展了该行为。
所提出的语义相当简单[原文如此]:如果-m用于执行模块,则在根据顶级模块的语义执行模块之前,使用PEP 302导入机制来定位模块并检索其编译代码。
它继续进一步解释,python将识别模块来自的包,使用标准流程导入该包,并运行模块。根据我的理解,调用“python3 -m package.module”与调用:
-m标志将模块作为
__file__
而不是__main__
运行。它还会将本地目录插入sys.path中,而不是脚本的目录。因此,它打破了相对进口,尽管这不是故意的,因此作者建议始终使用绝对进口。这也取决于你如何称呼它-“python3 -m package.module”和“python3 -m module”是不一样的。**理论上很简单-它加载python并导入模块,而不是将代码转储到
__main__
中。这是一个不同的导入系统,其行为不同。其中一些更改不是故意的,只是在实施后才发现。Python的导入是一团乱,被搞混是可以的。x33g5p2x7#
令人惊讶的是,当有些人说这个问题太简单而不值得费心时,这是如此难以回答。
据我所知,实际用途是当您不在目录中时,可以使用点表示法运行脚本。
可以运行
python -m path.to.my.happy.place
而不是在
path/to/my/happy
中运行python place.py
owfi6suc8#
如果你安装了多个版本的python,你想升级pip
pip install --upgrade pip
,你怎么知道哪个python版本会受到影响?它取决于shell的路径变量。在这种情况下,您也可能会收到警告。为了避免这种混淆,使用-m
,然后在变量sys.path中查找。这是-m
的另一个优点。