On Thu, May 28, 2020 at 9:03 PM Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
On 29/05/20 8:05 am, tritium-list@sdamon.com wrote:

> People write main entry points that are not exactly this?
>
> If __name__ == '__main__':
>      sys.exit(main(sys.argv[1:]))

It's not clear that exiting with the return value of main() is
the most Pythonic thing to do -- it's more of a C idiom that
doesn't seem so useful when exceptions exist.

If all you care about in terms of exit codes is 0 for success and 1 for error (which is sufficient for most scripts), then yes, this is probably not needed.

However, it's useful in two cases. One is if you're writing a script tool to be distributed, where you probably want to have a blanket "except Exception" clause in main() to catch everything and print a graceful failure message. In that case, you probably want to suppress the ugly traceback, which requires manually producing the appropriate exit code (probably 1, but maybe something else).

Additionally, you might be writing a tool with more complex exit codes that are part of its documented API. A few GNU tools are like this ("diff" is the first example that comes to mind). Especially if you want to write a (mostly) drop-in replacement for such a tool, mimicking the exit code behavior can be critical.

So this type of entry point is useful even in Python, and tools that generate entry point scripts* should continue to generate code like this. It works even if you never put a return statement in main(), since the script exits on its own with 1 on an unhandled exception, and the implicit "return None" at the end of main() is treated by sys.exit as 0.

*pip, for example, does this. It's worth noting that most instances I've seen of this have been automatically generated scripts like those; I've rarely seen a handwritten example. And most cases of this that I see, including pip's scripts, don't pass anything to main(), because you can always get the argv from the sys module (and sys.argv[0] can be useful in some cases).