Python main() Function

From GM-RKB
Jump to navigation Jump to search

A Python main() Function is a Python function that ...

  • Context:
    • It can (often) be executed when the Python script is executed within an if __name__ == '__main__': statement (not when the script is imported).
  • See: Python, Argparse.


References

2017

  • https://stackoverflow.com/a/42747728
    • QUOTE: ... To clarify how __main__ and the function main() works. When you execute a module it will have a name which is stored in __name__. If you execute the module stand alone as a script it will have the name __main__. If you execute it as part of a module ie import it into another module it will have the name of the module.

      The function main() can be named anything you would like, and that wouldn't affect your program. It's commonly named main in small scripts but it's not a particularly good name if it's part of a larger body of code.

      In terms letting a user to input arguments when running as a script I would look into either using argparse or click.

      An example of how argparse would work.

if __name__ == '__main__':
   import argparse
   parser = argparse.ArgumentParser(description='Create a ArcHydro schema')
   parser.add_argument('--workspace', metavar='path', required=True,
                       help='the path to workspace')
   parser.add_argument('--schema', metavar='path', required=True,
                       help='path to schema')
   parser.add_argument('--dem', metavar='path', required=True,
                       help='path to dem')
   args = parser.parse_args()
   main(workspace=args.workspace, schema=args.schema, dem=args.dem)

2014

  • https://stackoverflow.com/a/22493194
    • QUOTE: The Python approach to "main" is almost unique to the language(*).

      The semantics are a bit subtle. The __name__ identifier is bound to the name of any module as it's being imported. However, when a file is being executed then __name__ is set to "__main__" (the literal string: __main__).

      This is almost always used to separate the portion of code which should be executed from the portions of code which define functionality. So Python code often contains a line like:

#!/usr/bin/env python
from __future__ import print_function
import this, that, other, stuff
class SomeObject(object):
   pass

def some_function(*args,**kwargs): pass
if __name__ == '__main__': print("This only executes when %s is executed rather than imported" % __file__)

Using this convention one can have a file define classes and functions for use in other programs, and also include code to evaluate only when the file is called as a standalone script.

It's important to understand that all of the code above the if __name__ line is being executed, evaluated, in both cases. It's evaluated by the interpreter when the file is imported or when it's executed. If you put a print statement before the if __name__ line then it will print output every time any other code attempts to import that as a module. (Of course, this would be anti-social. Don't do that).

I, personally, like these semantics. It encourages programmers to separate functionality (definitions) from function (execution) and encourages re-use.

Ideally almost every Python module can do something useful if called from the command line. In many cases this is used for managing unit tests. If a particular file defines functionality which is only useful in the context of other components of a system then one can still use __name__ == "__main__" to isolate a block of code which calls a suite of unit tests that apply to this module.

(If you're not going to have any such functionality nor unit tests than it's best to ensure that the file mode is NOT executable).

Summary: if __name__ == '__main__': has two primary use cases:

  • Allow a module to provide functionality for import into other code while also providing useful semantics as a standalone script (a command line wrapper around the functionality)
  • Allow a module to define a suite of unit tests which are stored with (in the same file as) the code to be tested and which can be executed independently of the rest of the codebase.

It's fairly common to def main(*args) and have if __name__ == '__main__': simply call main(*sys.argv[1:]) if you want to define main in a manner that's similar to some other programming languages. If your .py file is primarily intended to be used as a module in other code then you might def test_module() and calling test_module() in your if __name__ == '__main__:' suite.