Ned*_*der 287
通常,通过在命令行上命名.py文件来运行Python程序:
$ python my_program.py
Run Code Online (Sandbox Code Playgroud)
您还可以创建一个充满代码的目录或zipfile,并包含一个__main__.py
.然后,您只需在命令行上命名目录或zipfile,它就会__main__.py
自动执行:
$ python my_program_dir
$ python my_program.zip
# Or, if the program is accessible as a module
$ python -m my_program
Run Code Online (Sandbox Code Playgroud)
您必须自己决定您的应用程序是否可以从这样执行中受益.
请注意,__main__
模块通常不是来自__main__.py
文件.它可以,但通常不会.运行类似脚本时python my_program.py
,脚本将作为__main__
模块而不是my_program
模块运行.对于python -m my_module
以其他方式运行的模块,也会发生这种情况.
如果您__main__
在错误消息中看到该名称,那并不一定意味着您应该查找__main__.py
文件.
Aar*_*all 87
该
__main__.py
文件是什么?
在创建Python模块时,通常使模块在main
作为程序的入口点运行时执行某些功能(通常包含在函数中).这通常通过放置在大多数Python文件底部的以下常用习惯来完成:
if __name__ == '__main__':
# execute only if run as the entry point into the program
main()
Run Code Online (Sandbox Code Playgroud)
你可以用Python获得相同的语义__main__.py
.这是一个linux shell提示符,$
如果你在Windows上没有Bash(或另一个Posix shell),只需在demo/__<init/main>__.py
EOF 上创建这些文件:
$ mkdir demo
$ cat > demo/__init__.py << EOF
print('demo/__init__.py executed')
def main():
print('main executed')
EOF
$ cat > demo/__main__.py << EOF
print('demo/__main__.py executed')
from __init__ import main
main()
EOF
Run Code Online (Sandbox Code Playgroud)
(在Posix/Bash shell中,您可以通过在每个cat命令的末尾输入Ctrl-D(文件结尾字符)来执行上述操作而不使用EOF
s和结束<< EOF
s
现在:
$ python demo
demo/__main__.py executed
demo/__init__.py executed
main executed
Run Code Online (Sandbox Code Playgroud)
您可以从文档中获得此信息.该文件说:
EOF
- 顶级脚本环境
__main__
是顶级代码执行的范围的名称.模块的'__main__'
设置等于__name__
从标准输入,脚本或交互式提示中读取的内容.模块可以通过检查它自己来检测它是否在主作用域中运行
'__main__'
,这允许在模块作为脚本运行时有条件地执行模块中的常用习惯用法,或者__name__
在导入时使用但不是Run Code Online (Sandbox Code Playgroud)if __name__ == '__main__': # execute only if run as a script main()
对于包,通过包含一个
python -m
模块可以实现相同的效果, 模块的内容将在运行模块时执行__main__.py
.
您也可以将它打包到一个文件中并从命令行运行它 - 但请注意,压缩包不能执行子包或子模块作为入口点:
$ python -m zipfile -c demo.zip demo/*
$ python demo.zip
demo/__main__.py executed
demo/__init__.py executed
main() executed
Run Code Online (Sandbox Code Playgroud)
Blu*_*ers 28
__main__.py
用于zip文件中的python程序.该__main__.py
文件将在zip文件运行时执行.例如,如果zip文件是这样的:
test.zip
__main__.py
Run Code Online (Sandbox Code Playgroud)
和的内容__main__.py
是
import sys
print "hello %s" % sys.argv[1]
Run Code Online (Sandbox Code Playgroud)
那么如果我们要跑,python test.zip world
我们就会hello world
离开.
因此,__main__.py
当在zip文件上调用python时,文件会运行.
ana*_*nik 20
创建__main__.py
于yourpackage
使其可执行文件:
$ python -m yourpackage
Run Code Online (Sandbox Code Playgroud)
Tas*_*nou 20
这里的一些答案暗示,给定一个__init__.py
包含__main__.py
文件的“包”目录(带有或不带有显式文件),使用-m
开关运行该目录与不使用开关没有区别。
大不同的是,没有在-m
开关,该“包”的目录首先被添加到路径(即sys.path中),然后将文件被运行正常,无包语义。
而与该-m
开关,包语义(包括相对进口)很荣幸,和包目录本身是永远不会添加到系统路径。
这是一个非常重要的区别,无论是在相对导入是否有效方面,更重要的是在规定在系统模块意外遮蔽的情况下将导入什么方面。
例子:
考虑一个PkgTest
具有以下结构的目录
:~/PkgTest$ tree
.
??? pkgname
? ??? __main__.py
? ??? secondtest.py
? ??? testmodule.py
??? testmodule.py
Run Code Online (Sandbox Code Playgroud)
其中__main__.py
文件具有以下内容:
:~/PkgTest$ cat pkgname/__main__.py
import os
print( "Hello from pkgname.__main__.py. I am the file", os.path.abspath( __file__ ) )
print( "I am being accessed from", os.path.abspath( os.curdir ) )
from testmodule import main as firstmain; firstmain()
from .secondtest import main as secondmain; secondmain()
Run Code Online (Sandbox Code Playgroud)
(其他文件的定义类似,打印输出类似)。
如果你在没有-m
开关的情况下运行它,这就是你会得到的。请注意,相对导入失败,但更重要的是请注意选择了错误的测试模块(即相对于工作目录):
:~/PkgTest$ python3 pkgname
Hello from pkgname.__main__.py. I am the file ~/PkgTest/pkgname/__main__.py
I am being accessed from ~/PkgTest
Hello from testmodule.py. I am the file ~/PkgTest/pkgname/testmodule.py
I am being accessed from ~/PkgTest
Traceback (most recent call last):
File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/usr/lib/python3.6/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "pkgname/__main__.py", line 10, in <module>
from .secondtest import main as secondmain
ImportError: attempted relative import with no known parent package
Run Code Online (Sandbox Code Playgroud)
而使用 -m 开关,你会得到你(希望)所期望的:
:~/PkgTest$ python3 -m pkgname
Hello from pkgname.__main__.py. I am the file ~/PkgTest/pkgname/__main__.py
I am being accessed from ~/PkgTest
Hello from testmodule.py. I am the file ~/PkgTest/testmodule.py
I am being accessed from ~/PkgTest
Hello from secondtest.py. I am the file ~/PkgTest/pkgname/secondtest.py
I am being accessed from ~/PkgTest
Run Code Online (Sandbox Code Playgroud)
注意:老实说,-m
应该避免空跑。事实上,我会更进一步说我会executable packages
以这样的方式创建任何东西,除非通过-m
交换机运行,否则它们会失败。
换句话说,假设所有其他导入都代表系统模块,我只会通过“相对导入”显式从“包内”模块导入。如果有人试图在没有-m
开关的情况下运行您的包,相关的导入语句将抛出错误,而不是静默运行错误的模块。