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: whenmain()
callssys.exit()
, your interactive Python interpreter will exit! The remedy is to letmain()
's return value specify the exit status. Thus, the code at the very end becomesif __name__ == "__main__": sys.exit(main())
and the calls to
sys.exit(n)
insidemain()
all becomereturn 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.
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
.
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