【发布时间】:2014-05-17 17:30:55
【问题描述】:
BDFL 发布于 2003 年 an article about how to write a Python main function。他的例子是这样的:
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() 的原因是,“我们将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) 之间来回切换。
我知道我可以从getopt 中捕获SystemExit,或者尝试使用一些黑魔法来检测Python 是否以交互方式运行,但我认为这两者都不是BDFL 的意图。
【问题讨论】:
-
“我的意图是只导入具有这种 main() 类型的模块,而不是只使用 execfile 或 runfile 执行它们吗?”是的,我相信是的。为什么要使用
execfile或runfile? -
是的,你需要
import它。当您执行/运行它时,__name__是__main__并且最后的sys.exit会运行。 -
@BrenBarn 问道,“为什么要使用
execfile或runfile?”假设我正在尝试编写一个中等复杂的函数。我将尝试在控制台中运行它几次,返回源文件并进行一些编辑,按 F5 执行该文件,然后再次从控制台对其进行测试。import在这种情况下效果不佳。这不是典型的吗? -
@kuzzooroo:我认为不典型的是想要这样做和想要以交互方式使用该功能但仍然具有相同的组合脚本可以作为主要运行。脚本导入一次后,可以使用
reload重新加载。 -
最多,这是您的 IDE 的问题,当它运行的代码调用
sys.exit时,它会关闭其嵌入式解释器。也许它应该在顶层默默地捕捉到那个异常,让你继续以交互方式做事。或者,您可以放弃程序返回值,只从您的if __name__ == "__main__"块中调用main()而无需sys.exit包装。