如何在使用 execfile 时防止运行 __main__ 守卫?
BDFL在2003年发了一篇文章,讲的是如何写一个Python的主函数。文章里给了一个例子:
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())
这个主函数里的可选参数argv
的意思是,“我们把main()
改成可以接受一个可选的argv
参数,这样我们就可以在Python的交互式提示符下调用它。”
他对代码最后一行的解释是:
现在
sys.exit()
的调用有点麻烦:当main()
调用sys.exit()
时,你的交互式Python解释器会直接退出!解决办法是让main()
的返回值来指定退出状态。因此,最后的代码变成了:if __name__ == "__main__": sys.exit(main())
而在
main()
内部对sys.exit(n)
的调用都变成了return n
。
不过,当我在Spyder控制台运行Guido的代码时,它会直接关闭解释器。我是不是漏掉了什么?是不是说我只能import
那些有这种类型main()
的模块,而不能直接用execfile
或runfile
来执行它们?这不是我平常做交互式开发的方式,尤其是这还要求我记得在import foo
和reload(foo)
之间来回切换。
我知道我可以捕获SystemExit
,或者试着用一些黑魔法来检测Python是否在交互模式下运行,但我想这都不是BDFL的本意。
2 个回答
0
还有一种处理方法,我在问题中稍微提到过,就是尝试检测你是否处于一个互动的环境中。我认为这并不能在所有情况下都适用,但如果对某些人有帮助的话,可以看看这个方法:
if __name__ == "__main__":
if 'PYTHONSTARTUP' in os.environ:
try:
main() # Or whatever you want to do here
except SystemExit as se:
logging.exception("")
else:
sys.exit(main())
11
你有两个选择:要么不使用 execfile
,要么传入一个不同的 __name__
值作为全局变量。
execfile('test.py', {'__name__': 'test'})
默认情况下,运行这个文件就像运行一个脚本,这样 __name__
的值会被设置为 __main__
。
你提到的那篇文章只适用于 import
。