python -m pip install <package>
时,与仅使用pip install <package>
有何不同?同样,为什么我要写python -m pip install --upgrade pip
来升级Pip,而不是直接使用pip install --upgrade pip
呢?python -m pip install <package>
时,与仅使用pip install <package>
有何不同?同样,为什么我要写python -m pip install --upgrade pip
来升级Pip,而不是直接使用pip install --upgrade pip
呢?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
)时,该列表从第一个目录遍历到最后一个目录,搜索与您输入的命令匹配的文件名。$PATH
,而在Windows系统上,则称为%PATH%
。-m
标志的更一般性评论(2022年12月)python -m some_module
时,-m
标志使Python将some_module
作为脚本执行。这在文档中有说明,但可能需要一些基本知识才能理解。some_module
通常通过在导入文件的顶部使用import some_module
语句导入到另一个Python文件中。这使得可以在导入文件中使用在some_module
中定义的函数、类和变量。
要将some_module
作为脚本而不是导入它,您需要在文件内部定义一个if __name__ == "__main__"
块。当在命令行上运行python some_module.py
时,将执行此块。这很有用,因为您不希望在导入其他文件时运行此代码块,但您希望在从命令行调用时运行此代码块。python some_module.py
但是对于Python标准库中的模块,这种方法行不通。Python文档中的示例使用了timeit
(pip
也适用):
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在路径中查找timeit.py
并执行文件中的if __name__ == "__main__"
子句。
python3 -m timeit -s 'print("hello")'
这个按预期工作。
if __name__ == "__main__"
代码块的源代码可以在 这里 找到,它是 timeit 模块的一部分。
来自Python文档:
由于参数是模块名,因此不应给出文件扩展名(.py),
module-name
应该是有效的Python模块名称,但实现可能并不总是强制执行此规定(例如,它可能允许您使用包括连字符的名称)。还允许使用软件包名称。 当提供软件包名称而不是普通模块时,解释器将执行
<pkg>.__main__
作为主模块。 这种行为故意与作为脚本参数传递给解释器的目录和zipfile的处理方式类似。
如果您输入python --help
您将得到:
// More flags above
-m mod : run library module as a script (terminates option list)
// and more flags below
如果您使用command --help
或 man command
,终端中的许多内容都会向您展示如何使用它。
python -m pip [flags]
,您不必提供 pip.py
存在的目录路径或将其作为当前工作目录。相反,Python 本身通过 PYTHONPATH 导入 pip 模块并运行它,这也意味着当加载和执行 pip.py 或任何其他“作为模块”运行的脚本时,它们都不会具有 __name__ == '__main__'
。 - nigh_anxiety-m
与 python
语句,并跟上一个 <module_name>
时,可以将该模块作为可执行文件运行。python --help
获取更多信息。-m
标志。当我没有使用它时,我的脚本总是可以正常运行的。 - Charlie Parker-m
标志是非常有用的,因为它将在 sys.path
中所有可用的路径中搜索模块/包,而不仅仅是当前工作目录。 - qwerty_urlpython timeit
,并且当前工作目录中没有名为 timeit
的文件/文件夹,则会出现“没有这样的文件或目录”错误。但是,如果你添加 -m
标志,那么 Python 将运行标准库中附带的 timeit 包。 - qwerty_url这实际上是一个有趣的问题,让我们来探索由@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 module”不同。
理论上很简单——它加载Python并导入模块,而不是将代码转储到__main__
中。 实际上效果很多。 它是一个行为不同的不同导入系统。 其中有些变化并非有意,并且仅在实施后才被发现。 Python的导入机制比较混乱,如果感到困惑是正常的。
有些人说这个问题太简单了,不值得回答,但实际上这是一个很难回答的问题。
据我所知,它的实际用途是让你在不在目录中的情况下使用点符号来运行你的脚本。
你可以运行
python -m path.to.my.happy.place
而不必在 path/to/my/happy
目录中运行 python place.py
pip install --upgrade pip
,那么您如何知道哪个Python版本会受到影响?这取决于shell的路径变量。在这种情况下,您可能还会收到警告。为避免混淆,请使用-m
,然后它会查找sys.path变量。这是-m
的另一个优点。# importing module
import sys
# printing all directories for
# interpreter to search
sys.path