What is the __main__.py
file for, what sort of code should I put into it, and when should I have one?

- 626
- 7
- 26

- 16,498
- 15
- 50
- 52
-
Also see the section [main-py-in-python-packages](https://docs.python.org/3/library/__main__.html#main-py-in-python-packages) in the docs. – djvg Feb 22 '22 at 11:08
6 Answers
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.

- 260,549
- 28
- 431
- 505

- 364,293
- 75
- 561
- 662
-
45I found `python -m program_dir` and `python program_dir` a little different: the latter never runs `__init__.py` in the directory (if there is one). – kbridge4096 May 07 '18 at 03:46
-
7@brk: That doesn't seem to be the case now. I just tried `python3 program_dir` and it ran `__init__.py`. – mk12 Jan 03 '19 at 02:09
-
7@mk12 I just tried it I can confirm @brk's findings: `python3 dir` runs `__main__.py` but not `__init__.py`, whereas `python3 -m dir` runs both. – Marcello Romani Oct 29 '19 at 18:15
-
3@mk12 Probably you had some code within `__main__.py` which has triggered the import of `__init__.py` – wim Apr 24 '20 at 22:25
-
3I place `__main__.py` in the root of project, so developer can run `python .` and voila! – vintprox Jul 06 '20 at 12:02
-
1@brk the two behave differently (and the distinction is actually important, since it can lead to bugs). I have added an answer below to show this difference, in case it interests any future readers. – Tasos Papastylianou Nov 11 '20 at 14:13
-
1Good answer. Also helpful to read the answer by @TasosPapastylianou re: relative imports. – Luke W Nov 20 '20 at 21:04
-
How to call the main function in `__main__.py` within code? Because I get an error saying "Module has no attribute __main__". – Burak Kaymakci Dec 26 '20 at 22:52
-
What I would like to know, is it is possible to run `__main__.py` with `__name__` set to anything other than `"__main__"`? I have encountered a `__main__.py` with `if __name__ == "__main__"` in it, and I'm thinking this is completely redundant? `__name__` in `__main__.py` can never be anything other than `"__main__"`? ... ah I've just noticed one of the other answers has confirmed this is correct. – NeilG Dec 07 '22 at 10:22
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.

- 374,368
- 89
- 403
- 331
-
3Would you use `if __name__ == '__main__'` within `__main__.py`? Or is it unecessary? – Dan Mar 01 '21 at 21:11
-
3
-
1It's redundant, as you would never import `__main.py__` into another module. The `if __name__ == "__main__"` protective clause serves the purpose of protecting module-level code from being run on import. This wouldn't happen when you're building a `__main__.py` file. – preritdas Oct 30 '22 at 19:19
-
dude, the part where you use pathlib.Path.write_text to write Python code as string to a file is really ugly and totally useless. – upgrd Apr 03 '23 at 15:48
-
I find it useful because I (and other users of the site) can recreate the files by simply pasting the code into Python interpreter. – Russia Must Remove Putin Apr 04 '23 at 06:52
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.
Example:
Consider a directory called PkgTest
with the following structure
:~/PkgTest$ tree
.
├── pkgname
│ ├── __main__.py
│ ├── secondtest.py
│ └── testmodule.py
└── testmodule.py
where the __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 -m
switch.
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.

- 21,371
- 2
- 28
- 57
-
8Explanation of the implications for relative imports is very helpful, Thanks. – Luke W Nov 20 '20 at 20:57
-
4Shameless plug: In case it interests anyone, [here is a nice template I made](https://github.com/tpapastylianou/executable-python-package-template) for creating such self-contained, executable python packages. :) – Tasos Papastylianou Dec 31 '20 at 19:34
-
wait but if you wanted to use the `testmodule` the one from `PkgTest/pkgname` how will you do it forcing `-m`? – ShifraSec Jan 20 '22 at 06:11
-
1@ShifraSec You mean in the code? You can import it using a relative import, i.e. `from . testmodule import main` (note the dot!). Alternatively you can use the package name explicitly and say, e.g. `from pkgname import testmodule`. If you want to import _both_ in your code, you can load them under different names, e.g. `import testmodule as testmodule1; from pkgname import testmodule as testmodule2`. – Tasos Papastylianou Jan 20 '22 at 11:30
-
@Tasos Papastylianou ooh you are right, that's a basic thing I confused myself for a moment – ShifraSec Jan 22 '22 at 06:43
-
1@ShifraSec no worries. Not at all; it's the kind of thing you have to play around with until you get a good grip for it. :) – Tasos Papastylianou Jan 22 '22 at 14:01
You create __main__.py
in yourpackage
to make it executable as:
$ python -m yourpackage

- 57,944
- 17
- 167
- 143

- 19,847
- 9
- 124
- 140
-
2`-m` works if only the program is accessible as a module, else you could use `python
` NOTE: without `-m` option – Benyamin Jafari Aug 12 '18 at 12:27 -
1@BenyaminJafari it is not possible to write command line Python program that is not accessible as [a module](https://stackoverflow.com/questions/2996110/what-is-the-difference-between-a-module-and-a-script-in-python). Maybe you've meant `package`? – anatoly techtonik Aug 12 '18 at 19:44
-
1when we create a Python package which contains the __main__.py, to run it `python -m
` doesn't work, `-m` is a redundant option, but `python – Benyamin Jafari Aug 12 '18 at 20:17` works well. -
1@BenyaminJafari The -m flag does make a difference in some cases. Executing from directory `a` and assuming script `a/b/c/__main__.py`... `python -m b.c` will execute from the directory `a` and the main script's imports will be relative to `a`. But `python b/c` will execute from the import scope of dir `c` and so any imports like in the main script like `import b.d` will fail. – Michael Currin Aug 18 '19 at 09:28
-
2@BenyaminJafari this is dangerous advice. There is a very important difference between running with or without the `-m` switch. I have added an answer below to clarify this, for any future readers wondering about the difference. – Tasos Papastylianou Nov 11 '20 at 14:07
__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.

- 3,718
- 3
- 22
- 24
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.

- 87,717
- 12
- 108
- 131