是否使用-m选项执行Python代码
python解释器具有-m
模块 选项“将库模块 模块 作为脚本运行”。
使用此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
编译成a.pyc的python模块相同的东西。
这些调用之间的(实际)区别是什么?它们之间有什么利弊?
同样,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
和现在至少存在 可能性 的封装的,所以__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__']
。