In a project that has a __main__.py
, rather than
# __main__.py
# def main...
if __name__ == "__main__":
main()
...is it OK to just do:
# __main__.py
# def main...
main()
Edit:
@user2357112-supports-Monica's argument made a lot of sense to me, so I went back and tracked down the library that had been giving me issues, causing me to still be adding the if __...
line. It's upon calling python -m pytest --doctest-modules
.
Maybe that's the only place that makes a mistake in running __main__.py
? And maybe that's a bug?
Reproduced by putting the first example in the docs in a __main__.py
:
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― package/__main__.py ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
package/__main__.py:58: in <module>
args = parser.parse_args()
/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/argparse.py:1755: in parse_args
args, argv = self.parse_known_args(args, namespace)
/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/argparse.py:1787: in parse_known_args
namespace, args = self._parse_known_args(args, namespace)
/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/argparse.py:2022: in _parse_known_args
', '.join(required_actions))
/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/argparse.py:2508: in error
self.exit(2, _('%(prog)s: error: %(message)s\n') % args)
/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/argparse.py:2495: in exit
_sys.exit(status)
E SystemExit: 2
--------------------------------------------------------------------------------------- Captured stderr ---------------------------------------------------------------------------------------
usage: pytest.py [-h] [--sum] N [N ...]
pytest.py: error: the following arguments are required: N
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Results (4.23s):
If you import this script as a module in another script, the __name__ is set to the name of the script/module. Python files can act as either reusable modules, or as standalone programs. if __name__ == “main”: is used to execute some code only if the file was run directly, and not imported.
Python looks for a file named __main__.py to start its execution automatically. If it doesn't find it it will throw an error else it will execute main.py and from the code, you can well understand that it will import the modules from src to find the area.
We can use an if __name__ == "__main__" block to allow or prevent parts of code from being run when the modules are imported. When the Python interpreter reads a file, the __name__ variable is set as __main__ if the module being run, or as the module's name if it is imported.
__main__ is the name of the module, here as you are directly executing it, its being considered as a script and all scripts have the name __main__ in Python. There's a . in between because Fraction is an attribute of the script __main__ , the module; and belongs to the module level scope.
It's okay to skip the if __name__ == '__main__'
guard in most regular scripts, not just __main__.py
. The purpose of the guard is to make specific code not run if the file is imported as a module instead of run as the program's entry point, but importing a __main__.py
as a module is usually using it wrong anyway.
Even with multiprocessing
, you might think you need an if __name__ == '__main__'
guard, but in the case of a __main__.py
, it wouldn't actually help. It's commonly said that multiprocessing
in spawn or forkserver mode imports the __main__
script as a module, but that's a simplification of the real behavior. In particular, one part of the real behavior is that if spawn mode detects the main script was a __main__.py
, it just doesn't try to load the original __main__
at all:
# __main__.py files for packages, directories, zip archives, etc, run
# their "main only" code unconditionally, so we don't even try to
# populate anything in __main__, nor do we make any changes to
# __main__ attributes
current_main = sys.modules['__main__']
if mod_name == "__main__" or mod_name.endswith(".__main__"):
return
forkserver mode also didn't load __main__.py
when I tested it, but forkserver goes through a slightly different code path, and I'm not sure where it decided to skip __main__.py
.
(This might be different on different Python versions - I only checked 3.8.2.)
That said, there's nothing wrong with using an if __name__ == '__main__'
guard. Not using it has more weird edge cases than using it, and experienced readers will be more confused by its absence than its presence. Even in a __main__.py
, I would probably still use the guard.
If you actually do want to import __main__.py
for some reason, perhaps to unit test functions defined there, then you will need the guard. However, it might make more sense to move anything worth importing out of __main__.py
and into another file.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With