What is the
__main__.py file for, what sort of code should I put into it, and when should I have one?
__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:
and the contents of
import sys print "hello %s" % sys.argv
Then if we were to run
python test.zip world we would get
hello world out.
__main__.py file run when python is called on a zip file.
If your script is a directory or ZIP file rather than a single python file,
__main__.py will be executed when the “script” is passed as an argument to the python interpreter.
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
$ 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
yourpackage to make it executable as:
$ python -m yourpackage
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
>>> 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
$ 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.
__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
python -mbut 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__.pymodule, the contents of which will be executed when the module is run with
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
__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
Particularly relevant to the question –
zipapp causes the zipped directory to execute the
__main__.py by default – and it is executed first, before
$ 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.
Some of the answers here imply that given a "package" directory (with or without an explicit
__init__.py file), containing a
__main__.py file, there is no difference between running that directory with the
-m switch or without.
The big difference is that without the
-m switch, the "package" directory is first added to the path (i.e. sys.path), and then the files are run normally, without package semantics.
Whereas with the
-m switch, package semantics (including relative imports) are honoured, and the package directory itself is never added to the system path.
This is a very important distinction, both in terms of whether relative imports will work or not, but more importantly in terms of dictating what will be imported in the case of unintended shadowing of system modules.
Consider a directory called
PkgTest with the following structure
:~/PkgTest$ tree . ├── pkgname │ ├── __main__.py │ ├── secondtest.py │ └── testmodule.py └── testmodule.py
__main__.py file has the following contents:
:~/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()
(with the other files defined similarly with similar printouts).
If you run this without the
-m switch, this is what you’ll get. Note that the relative import fails, but more importantly note that the wrong testmodule has been chosen (i.e. relative to the working directory):
:~/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
Whereas with the -m switch, you get what you (hopefully) expected:
:~/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
Note: In my honest opinion, running without
-m should be avoided. In fact I would go further and say that I would create any
executable packages in such a way that they would fail unless run via the
In other words, I would only import from ‘in-package’ modules explicitly via ‘relative imports’, assuming that all other imports represent system modules. If someone attempts to run your package without the
-m switch, the relative import statements will throw an error, instead of silently running the wrong module.