当您使用-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__']
。