Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is "if __name__ == '__main__'" required in a __main__.py?

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):
like image 744
Maximilian Avatar asked Apr 24 '20 21:04

Maximilian


People also ask

What is if __ name __ in Python?

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.

What is the use of __ main __ PY?

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.

How do you write if name is main in Python?

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.

What is __ main __ class?

__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.


Video Answer


1 Answers

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.

like image 55
user2357112 supports Monica Avatar answered Oct 06 '22 02:10

user2357112 supports Monica