首先,您不应依赖异常的类名,而应依赖于类本身 - 来自两个不同模块的两个类可以具有相同的 __name__ 属性值,但它们是不同的异常。所以你想要的是:
try:
something_that_may_raise()
except IOError as e:
handle_io_error(e)
except SomeOtherError as e:
handle_some_other_error(e)
等等……
那么您有两种例外情况:一种是您可以实际处理的一种或另一种方式,另一种是另一种。如果程序仅供您个人使用,处理“其他程序”的最佳方法通常是根本不处理它们 - Python 运行时会捕获它们,显示带有所有相关信息的良好回溯(所以你知道发生了什么以及在哪里以及最终可以为这种情况添加一些处理)。
如果它是一个“公共”程序和/或如果您在程序崩溃之前确实需要清理一些东西,您可以在程序的顶层添加最后一个“catch all”except 子句,该子句将记录错误和回溯某处以免丢失(logging.exception 是您的朋友),清理必须清理的内容并以更友好的错误消息终止。
很少有人真的想忽略一个异常(我的意思是假装没有发生任何错误或意外并愉快地继续)。至少您将希望通知用户其中一个操作失败以及原因 - 在您的情况下,这可能是一个顶级循环迭代一组要废弃的站点,内部尝试/除块捕获“预期”错误情况,即:
# config:
config = [
# ('url', {params})
('some.site.tld', {"param1" : value1, "param2" : value2}),
('some.other.tld', {"param1" : value1, "answer" : 42}),
# etc
]
def run():
for url, params in config:
try:
results = scrap(url, **params)
except (SomeKnownError, SomeOtherExceptedException) as e:
# things that are to be expected and mostly harmless
#
# you configured your logger so that warnings only
# go to stderr
logger.warning("failed to scrap %s : %s - skipping", url, e)
except (MoreSeriousError, SomethingIWannaKnowAbout) as e:
# things that are more annoying and you want to know
# about but that shouldn't prevent from continuing
# with the remaining sites
#
# you configured your logger so that exceptions goes
# to both stderr and your email.
logger.exception("failed to scrap %s : %s - skipping", url, e)
else:
do_something_with(results)
然后在调用run() 周围有一个顶级处理程序来处理意外错误:
def main(argv):
parse_args()
try:
set_up_everything()
run()
return 0
except Exception as e:
logger.exception("oops, something unexpected happened : %s", e)
return 1
finally:
do_some_cleanup()
if __name__ == "__main__":
sys.exit(main(sys.argv))
请注意logging module has an SMTPHandler - 但是由于邮件也很容易失败,因此您最好在本地仍然拥有可靠的日志(stderr 和tee 到文件?)。 logging 模块需要一些时间来学习,但从长远来看它确实有回报。