是否使用-m选项执行Python代码 [英] Execution of Python code with -m option or not

查看:206
本文介绍了是否使用-m选项执行Python代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆