我在 python 2.7 和 Linux 上,如果我可以用 raise SystemExit 替换 sys.exit(1) ,我有一个简单的代码需要建议。
==实际代码==
def main():
try:
create_logdir()
create_dataset()
unittest.main()
except Exception as e:
logging.exception(e)
sys.exit(EXIT_STATUS_ERROR)
if __name__ == '__main__': main()
==更改代码==
def main():
try:
create_logdir()
create_dataset()
unittest.main()
except Exception as e:
logging.exception(e)
raise SystemExit
if __name__ == '__main__':
main()
我个人反对这两个。我喜欢的模式是这样的:
def main(argv):
try:
...
except Exception as e:
logging.exception(e)
return 1
if __name__ == '__main__':
sys.exit(main(sys.argv))
请注意, main() 恢复为具有正常返回的正常函数。
此外,我们大多数人会避免“异常除外”,而只是让顶层除外冒泡:这样您就可以获得堆栈回溯以进行调试。我同意它可以防止记录异常并导致更丑的控制台输出,但我认为这是一个胜利。如果您确实想记录异常,则总是这样:
尝试:...除了异常为 e:logging.exception(e) raise
将异常背诵到日志中,仍然让它正常冒泡。
“except Exception”模式的问题在于,它捕获并
隐藏了
每个异常,而不仅仅是您理解的特定异常的狭窄集合。
最后,不赞成提出一个裸露的 Exception 类。在 python 3 中,我相信它实际上是被禁止的,所以无论如何它都是不可移植的。但即使在 Python 中,最好提供一个 Exception 实例,而不是类:
引发 SystemExit(1)
try 块中的所有函数都使用 raise 冒泡了异常
这里的 create_logdir() 示例是函数定义
定义创建日志目录():
try: os.makedirs(LOG_DIR) 除了 OSError as e: sys.stderr.write("Failed to create log directory...Exiting !!!") raise print "log file:" + corrupt_log return True
def main(): try: create_logdir() except Exception as e: logging.exception(e) raise SystemExit
(a) 如果 create_logdir() 失败,我们将收到以下错误,这很好还是我需要改进此代码。
无法创建日志目录...正在退出 !!!ERROR:root:[Errno 17] 文件存在:'/var/log/dummy'
回溯(最后一次调用):文件“corrupt_test.py”,第 245 行,在 main create_logdir() 文件“corrupt_test.py”,第 53 行,在 create_logdir os.makedirs(LOG_DIR) 文件“/usr/local/lib/ python2.7/os.py",第 157 行,在 makedirs OSError: [Errno 17] 文件存在:'/var/log/dummy'
我更喜欢冒泡方法,可能像您所做的那样带有日志或警告消息,例如:
logging.exception("create_logdir failed: makedirs(%r): %s" % (LOG_DIR, e)) raise
(也不是该日志消息记录了更多上下文:上下文在调试问题时非常有用。)
对于非常小的脚本 sys.stderr.write 是可以的,但一般来说,你的任何被证明通常有用的函数都可能会迁移到库中以便被重用;考虑到 stderr 并不总是消息的地方;而是根据需要使用 error() 或 wanr() 或 exception() 读取日志记录模块。无需将输出连接到您的内部功能,配置输出的位置就可以有更多的空间。
我可以只 raise ,而不是 SystemExit 或 sys.exit(1) 。这对我来说看起来不对
定义主():
尝试:create_logdir() 例外为 e logging.exception(e) raise
这就是我自己会做的。
想一想:异常是否被“处理”了,意味着情况是否因为预期而得到处理?如果没有,让异常冒泡,以便用户知道发生了程序无法理解的事情。
最后,SystemExit 或 sys.exit() 从除了最外层的 main() 函数之外的任何东西中通常都是不好的。我什至在那里抗拒它;主函数,如果写得好,通常可以从其他有用的地方调用,这使得它有效地成为一个库函数(它已被重用)。这样的功能不应该单方面中止程序。真没礼貌!相反,让异常冒出来:也许 main() 的调用者期望它并且可以处理它。通过中止而不是“引发”,您剥夺了调用者做适当事情的机会,即使您自己(即“主要”)不知道足够的上下文来处理异常。
所以我是为了“提高”自己。然后只是因为您想记录错误。如果您不想记录异常,则可以完全避免 try/except 并使用更简单的代码:让调用者担心未处理的异常!