What is __main__.py?
Often, a Python program is run by naming a .py file on the command line:
$ python my_program.py
You can also create a directory or zipfile full of code, and include a __main__.py
. Then you can simply name the directory or zipfile on the command line, and it executes the __main__.py
automatically:
$ python my_program_dir
$ python my_program.zip
# Or, if the program is accessible as a module
$ python -m my_program
You'll have to decide for yourself whether your application could benefit from being executed like this.
Note that a __main__
module usually doesn't come from a __main__.py
file. It can, but it usually doesn't. When you run a script like python my_program.py
, the script will run as the __main__
module instead of the my_program
module. This also happens for modules run as python -m my_module
, or in several other ways.
If you saw the name __main__
in an error message, that doesn't necessarily mean you should be looking for a __main__.py
file.
What is the __main__.py
file for?
When creating a Python module, it is common to make the module execute some functionality (usually contained in a main
function) when run as the entry point of the program. This is typically done with the following common idiom placed at the bottom of most Python files:
if __name__ == '__main__':
# execute only if run as the entry point into the program
main()
You can get the same semantics for a Python package with __main__.py
, which might have the following structure:
.
└── demo
├── __init__.py
└── __main__.py
To see this, paste the below into a Python 3 shell:
from pathlib import Path
demo = Path.cwd() / 'demo'
demo.mkdir()
(demo / '__init__.py').write_text("""
print('demo/__init__.py executed')
def main():
print('main() executed')
""")
(demo / '__main__.py').write_text("""
print('demo/__main__.py executed')
from demo import main
main()
""")
We can treat demo as a package and actually import it, which executes the top-level code in the __init__.py
(but not the main
function):
>>> import demo
demo/__init__.py executed
When we use the package as the entry point to the program, we perform the code in the __main__.py
, which imports the __init__.py
first:
$ python -m demo
demo/__init__.py executed
demo/__main__.py executed
main() executed
You can derive this from the documentation. The documentation says:
__main__
— Top-level script environment
'__main__'
is the name of the scope in which top-level code executes. A module’s__name__
is set equal to'__main__'
when read from standard input, a script, or from an interactive prompt.A module can discover whether or not it is running in the main scope by checking its own
__name__
, which allows a common idiom for conditionally executing code in a module when it is run as a script or withpython -m
but not when it is imported:if __name__ == '__main__': # execute only if run as a script main()
For a package, the same effect can be achieved by including a
__main__.py
module, the contents of which will be executed when the module is run with-m
.
Zipped
You can also zip up this directory, including the __main__.py
, into a single file and run it from the command line like this - but note that zipped packages can't execute sub-packages or submodules as the entry point:
from pathlib import Path
demo = Path.cwd() / 'demo2'
demo.mkdir()
(demo / '__init__.py').write_text("""
print('demo2/__init__.py executed')
def main():
print('main() executed')
""")
(demo / '__main__.py').write_text("""
print('demo2/__main__.py executed')
from __init__ import main
main()
""")
Note the subtle change - we are importing main
from __init__
instead of demo2
- this zipped directory is not being treated as a package, but as a directory of scripts. So it must be used without the -m
flag.
Particularly relevant to the question - zipapp
causes the zipped directory to execute the __main__.py
by default - and it is executed first, before __init__.py
:
$ python -m zipapp demo2 -o demo2zip
$ python demo2zip
demo2/__main__.py executed
demo2/__init__.py executed
main() executed
Note again, this zipped directory is not a package - you cannot import it either.
__main__.py
is used for python programs in zip files. The __main__.py
file will be executed when the zip file in run. For example, if the zip file was as such:
test.zip
__main__.py
and the contents of __main__.py
was
import sys
print "hello %s" % sys.argv[1]
Then if we were to run python test.zip world
we would get hello world
out.
So the __main__.py
file run when python is called on a zip file.
You create __main__.py
in yourpackage
to make it executable as:
$ python -m yourpackage