是否使用-m选项执行Python代码 [英] Execution of Python code with -m option or not
问题描述
python解释器具有-m
module 选项,该选项将库模块 module 作为脚本运行".
使用此python代码a.py:
if __name__ == "__main__":
print __package__
print __name__
我测试了python -m a
以获得
"" <-- Empty String
__main__
python a.py
返回
None <-- None
__main__
对我来说,这两个调用似乎是相同的,只是当使用-m选项调用__package__时不为None.
有趣的是,使用python -m runpy a
时,我得到的与python -m a
相同,而python模块经过编译以获取a.pyc.
这些调用之间的(实际)区别是什么?他们之间有什么利弊吗?
此外,David Beazley的Python Essential Reference将其解释为"-m选项将库模块作为脚本运行,并在执行主脚本之前在__main__模块内部执行".是什么意思?
使用 -m
命令行标志,Python将为您导入模块或包,然后将其作为脚本运行.当您不使用-m
标志时,您命名的文件将作为一个脚本运行.
当您尝试运行软件包时,区别很重要.两者之间有很大的区别
python foo/bar/baz.py
和
python -m foo.bar.baz
在后一种情况下,将导入foo.bar
,并且相对导入将以foo.bar
为起点正确运行.
演示:
$ mkdir -p test/foo/bar
$ touch test/foo/__init__.py
$ touch test/foo/bar/__init__.py
$ cat << EOF > test/foo/bar/baz.py
> if __name__ == "__main__":
> print __package__
> print __name__
>
> EOF
$ PYTHONPATH=test python test/foo/bar/baz.py
None
__main__
$ PYTHONPATH=test python -m foo.bar.baz
foo.bar
__main__
因此,使用-m
开关时,Python实际上必须关心软件包.普通脚本永远不会成为包,因此__package__
设置为None
.
但是在带有-m
的包中运行包或模块 内,现在至少有包的 possibility ,因此设置了__package__
变量到一个字符串值;在上面的演示中,将其设置为foo.bar
,对于不在包内的普通模块,将其设置为空字符串.
关于__main__
模块; Python会像常规模块一样导入正在运行的脚本.创建一个新的模块对象以保存存储在sys.modules['__main__']
中的全局名称空间.这就是__name__
变量所指的,它是该结构中的关键.
对于软件包,您可以创建一个__main__.py
模块,并在运行python -m package_name
时运行该模块;实际上,这是您 可以将脚本作为脚本运行包的唯一方法:
$ PYTHONPATH=test python -m foo.bar
python: No module named foo.bar.__main__; 'foo.bar' is a package and cannot be directly executed
$ cp test/foo/bar/baz.py test/foo/bar/__main__.py
$ PYTHONPATH=test python -m foo.bar
foo.bar
__main__
因此,在命名要与-m
一起运行的程序包时,Python将查找该程序包中包含的__main__
模块并将其作为脚本执行.然后,其名称仍设置为__main__
,并且模块对象仍存储在sys.modules['__main__']
中.
The python interpreter has -m
module option that "Runs library module module as a script".
With this python code a.py:
if __name__ == "__main__":
print __package__
print __name__
I tested python -m a
to get
"" <-- Empty String
__main__
whereas python a.py
returns
None <-- None
__main__
To me, those two invocation seems to be the same except __package__ is not None when invoked with -m option.
Interestingly, with python -m runpy a
, I get the same as python -m a
with python module compiled to get a.pyc.
What's the (practical) difference between these invocations? Any pros and cons between them?
Also, David Beazley's Python Essential Reference explains it as "The -m option runs a library module as a script which executes inside the __main__ module prior to the execution of the main script". What does it mean?
When you use the -m
command-line flag, Python will import a module or package for you, then run it as a script. When you don't use the -m
flag, the file you named is run as just a script.
The distinction is important when you try to run a package. There is a big difference between:
python foo/bar/baz.py
and
python -m foo.bar.baz
as in the latter case, foo.bar
is imported and relative imports will work correctly with foo.bar
as the starting point.
Demo:
$ mkdir -p test/foo/bar
$ touch test/foo/__init__.py
$ touch test/foo/bar/__init__.py
$ cat << EOF > test/foo/bar/baz.py
> if __name__ == "__main__":
> print __package__
> print __name__
>
> EOF
$ PYTHONPATH=test python test/foo/bar/baz.py
None
__main__
$ PYTHONPATH=test python -m foo.bar.baz
foo.bar
__main__
As a result, Python has to actually care about packages when using the -m
switch. A normal script can never be a package, so __package__
is set to None
.
But run a package or module inside a package with -m
and now there is at least the possibility of a package, so the __package__
variable is set to a string value; in the above demonstration it is set to foo.bar
, for plain modules not inside a package, it is set to an empty string.
As for the __main__
module; Python imports scripts being run as it would a regular module. A new module object is created to hold the global namespace, stored in sys.modules['__main__']
. This is what the __name__
variable refers to, it is a key in that structure.
For packages, you can create a __main__.py
module and have that run when running python -m package_name
; in fact that's the only way you can run a package as a script:
$ PYTHONPATH=test python -m foo.bar
python: No module named foo.bar.__main__; 'foo.bar' is a package and cannot be directly executed
$ cp test/foo/bar/baz.py test/foo/bar/__main__.py
$ PYTHONPATH=test python -m foo.bar
foo.bar
__main__
So, when naming a package for running with -m
, Python looks for a __main__
module contained in that package and executes that as a script. It's name is then still set to __main__
, and the module object is still stored in sys.modules['__main__']
.
这篇关于是否使用-m选项执行Python代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!