你能给我解释一下打电话和打电话的区别吗

python -m mymod1 mymod2.py args

and

python mymod1.py mymod2.py args

在这两种情况下,似乎都调用了mymod1.py和sys. py。argv是

['mymod1.py', 'mymod2.py', 'args']

那么-m开关是干什么用的呢?


当前回答

我只想提一个可能令人困惑的例子。

假设使用pip3安装一个包foo,其中包含一个bar模块。这意味着你可以执行python3 -m foo。Bar从任何目录。另一方面,你有一个这样的目录结构:

src
|
+-- foo
    |
    +-- __init__.py
    |
    +-- bar.py

你在src/。当你运行python -m foo。Bar,您运行的是Bar .py,而不是已安装的模块。然而,如果你正在调用python -m foo。Bar从任何其他目录,您正在使用已安装的模块。

如果使用python而不是python -m,这种行为当然不会发生,初学者可能会感到困惑。原因在于Python搜索模块的顺序。

其他回答

由于当你使用“python -m”时出现了这个问题,我只是想为那些喜欢模块化代码而不创建完整的python包或修改PYTHONPATH或sys. m的人添加一个快速参考。路径。

设置

让我们设置下面的文件结构

.
├── f1
│   ├── f2
│   │   ├── __init__.py
│   │   └── test2.py
│   ├── __init__.py
│   └── test1.py
└── test.py

设当前路径为m1。

使用python -m代替python ./*

Use . qualified module names for the files (because they're being treated as modules now). For example, to run the contents in ./f1/test1.py, we do python -m f1.test1 and not python ./f1/test1.py When using the module method, the sys.path in test1.py (when that is run) is m1. When using the ./ (relative file) method, the path is m1/f1. So we can access all files in m1 (and assume that it is a full python package) using -m. This is because the path to m1 is stored (as PYTHONPATH). If we want to run deeply nested "modules", we can still use . (just as we do in import statements). # This can be done python -m f1.f2.test2 And in test2.py, we can do from f1.test1 import do_something without using any path gimmicks in it. Every time we do module imports this way, the __init__.py is automatically called. This is true even when we're nesting. python -m f1.f2.test2 When we do that, the ./f1/__init__.py is called, followed by ./f1/f2/__init__.py.

我只想提一个可能令人困惑的例子。

假设使用pip3安装一个包foo,其中包含一个bar模块。这意味着你可以执行python3 -m foo。Bar从任何目录。另一方面,你有一个这样的目录结构:

src
|
+-- foo
    |
    +-- __init__.py
    |
    +-- bar.py

你在src/。当你运行python -m foo。Bar,您运行的是Bar .py,而不是已安装的模块。然而,如果你正在调用python -m foo。Bar从任何其他目录,您正在使用已安装的模块。

如果使用python而不是python -m,这种行为当然不会发生,初学者可能会感到困惑。原因在于Python搜索模块的顺序。

值得一提的是,这只适用于包有一个文件__main__.py,否则,这个包不能直接执行。

python -m some_package some_arguments

python解释器将在要执行的包路径中查找__main__.py文件。它相当于:

python path_to_package/__main__.py somearguments

它将执行以下内容:

if __name__ == "__main__":

简而言之,'python -m'开关的最佳用例之一是当你想告诉python你想运行一个模块而不是执行一个.py文件时。

考虑这个例子:你在名为“venv”的文件中有一个Python脚本(没有“.py”文件扩展名)。如果你发出这个命令:

python venv

然后,Python将执行当前目录下的“venv”文件。然而,如果你想使用'python venv'模块创建一个新的虚拟环境,你可以运行:

python -m venv

在这种情况下,Python将运行'venv'模块,而不是'venv'文件。

另一个例子,如果你想运行Pyhton内置的本地http服务器并发出命令:

python http.server

你会得到这样一个错误:

python: can't open file '/home/user/http.server': [Errno 2] No such file or directory

这是因为Python试图执行一个名为“http”的文件。但没有找到。 因此,你想要发出相同的命令,但使用'-m'开关:

python -m http.server

这样Python就知道你想要模块的http。服务器不是文件。

PEP 338的基本原理部分的第一行说:

Python 2.4增加了命令行开关-m,允许使用Python模块名称空间定位模块,以便作为脚本执行。鼓舞人心的例子是标准库模块,如pdb和profile, Python 2.4实现可以很好地实现这个有限的目的。

所以你可以用这种方式指定Python搜索路径中的任何模块,而不仅仅是当前目录中的文件。你是正确的,python mymod1.py mymod2.py args具有完全相同的效果。本提案部分范围的第一行规定:

在Python 2.4中,使用-m定位的模块会被执行,就好像它的文件名已经在命令行上提供了一样。

使用-m可以做更多的事情,比如处理作为包的一部分的模块,等等。这就是PEP 338的其余内容。阅读它以获得更多信息。