首页 > 解决方案 > 异常处理的良好实践

问题描述

我想就 Python 中的异常处理的良好实践提供一些建议。

如果我以一个使用该库的简单程序socket为例,我会有这样的代码块:

try:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('127.0.0.1', 6666))
except OSError as e:
    if e.errno == 98:
        log.error('Address already in use')
    else:
        raise

我的问题是:像这样处理异常是否有趣,因为我可以简单地引发它并且堆栈跟踪将打印在我的日志文件中?

我的观点是,如果没有通过特定进程处理异常(例如调用特定函数,或更新某些上下文或其他),那么我不会仅仅记录一条消息,而这正是我所拥有的引发异常。

但同时,我认为干净的代码应该捕获可能出现的明显异常,并尝试在通用except子句中处理所有其他类型的异常,以防万一。

您对这个特定问题有何看法?

非常感谢。

标签: pythonexception

解决方案


想象一下你的try语句在一个循环体中,它尝试绑定到各种地址,直到你找到一个可用的地址。在这种情况下,如果地址已经在使用中,则通过确认它发生并转移到下一个可能的地址来完全“处理”异常。

addresses_to_try = [...]

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

for address in addresses_to_try:
    try:
        sock.bind(address, 6666)
        break
    except OSError as e:
        if e.errno == errno.EADDRINUSE:
            log.warning("%s already in use, trying the next address", address)
        else:
            raise
else:
    raise OSError(errno.EADDRINUSE, "All addresses in use")

处理异常也可能意味着您知道无法从错误中恢复,并且您绝对需要退出程序。重新引发异常只是表示您不知道如何从此处的错误中恢复,但调用堆栈中更高级别的人可能知道如何,并且您正在给他们这样做的机会。

try:
    sock.bind(address, 6666)
except OSError as e:
    if e.errno == errno.EADDRINUSE:
        sys.exit("The only and only possible address is not available")
    else:
        log.error("Something when wrong binding to %s", address)
        log.error("Maybe someone else can do something about it.")
        raise

推荐阅读