Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent running the __main__ guard when using execfile?

Tags:

python

main

exit

The BDFL posted in 2003 an article about how to write a Python main function. His example is this:

import sys
import getopt

class Usage(Exception):
    def __init__(self, msg):
        self.msg = msg

def main(argv=None):
    if argv is None:
        argv = sys.argv
    try:
        try:
            opts, args = getopt.getopt(argv[1:], "h", ["help"])
        except getopt.error, msg:
             raise Usage(msg)
        # more code, unchanged
    except Usage, err:
        print >>sys.stderr, err.msg
        print >>sys.stderr, "for help use --help"
        return 2

if __name__ == "__main__":
    sys.exit(main())

The reason for the optional argument argv to main() is, "We change main() to take an optional argv argument, which allows us to call it from the interactive Python prompt."

He explains the last line of his code like this:

Now the sys.exit() calls are annoying: when main() calls sys.exit(), your interactive Python interpreter will exit! The remedy is to let main()'s return value specify the exit status. Thus, the code at the very end becomes

if __name__ == "__main__":
    sys.exit(main())

and the calls to sys.exit(n) inside main() all become return n.

However, when I run Guido's code in a Spyder console, it kills the interpreter. What am I missing here? Is the intention that I only import modules that have this type of main(), never just executing them with execfile or runfile? That's not how I tend to do interactive development, especially given that it would require me to remember to switch back and forth between import foo and reload(foo).

I know I can catch the SystemExit from getopt or try to use some black magic to detect whether Python is running interactively, but I assume neither of those is the BDFL's intent.

like image 457
kuzzooroo Avatar asked May 17 '14 17:05

kuzzooroo


1 Answers

Your options are to not use execfile or to pass in a different __name__ value as a global:

execfile('test.py', {'__name__': 'test'})

The default is to run the file as a script, which means that __name__ is set to __main__.

The article you cite only applies to import.

like image 116
Martijn Pieters Avatar answered Nov 14 '22 22:11

Martijn Pieters