【问题标题】:Rethrow Python exception with new type用新类型重新抛出 Python 异常
【发布时间】:2014-05-03 18:56:35
【问题描述】:

我有一个类NameDatabase 打开一个sqlite 文件。几件事 可能会出错,例如格式错误的数据库、错误的模式等。这通常会导致 一个例外(在我的情况下为sqlite3.Error)。

我不想让那个异常逃离我的班级。相反,我想给 调用者我自己的异常类(推理:除了NameDatabase我还有 图像和 GPS 轨迹的类,我想向呼叫者展示一个常见的 要处理的异常列表)。

首先,这是个好主意吗?其次,我该怎么做?

我当前的代码:

class FileParseError(...): pass

class NameDatabase:
    def __init__(self, fname):
        self.fname = fname
        try:
            self.conn = sqlite3.connect(fname)
            # Check if we can query the DB and if the schema is ok.
            self.conn.execute('SELECT count(*) FROM names')
        except sqlite3.Error:
            raise FileParseError("Not a valid database: '%s'", fname)

这可行,但会产生双重回溯(在处理上述异常期间,发生了另一个异常)。我最理想的是原始回溯,以及我自己的类型FileParseError 的异常(它可以存储有关原始异常的一些信息)。

我知道我可以使用 sys.exc_info() 在我的 异常处理程序并在外部重新引发异常,但这似乎 乱七八糟,因为我必须在 except 子句中设置一个标志来记住处理 之后出错。有没有更好的办法?

exc = None
try:
    ...
except sqlite3.Error:
    exc = sys.exc_info()
if exc:
    raise FileParseError("Invalid DB '%s': %s", fname, str(exc[1])), None, exc[2]

平台:Windows 上的 CPython 3.3。

类似问题:10555671 正是我现在所拥有的。我正在寻找避免双重回溯的东西,同时也避免手动设置exc 标志和重新检查后除外。

【问题讨论】:

    标签: python exception python-3.x


    【解决方案1】:

    您似乎想将新异常与现有异常关联起来。这可以通过使用PEP 3134 引入的语法来完成。或者,您可以使用 PEP 409 中添加的语法完全抑制前面的异常。

    要链接异常,请在except 语句中为捕获的异常指定一个带有as 的名称,然后在raise 语句的末尾使用带有from 的名称。像这样的:

    except sqlite3.Error as e:
        raise FileParseError("Not a valid database: '%s'", fname) from e
    

    如果您想完全抑制 sqlite 错误,而不仅仅是将其转换为另一种异常类型,您可以在 raise 语句中使用 from None

    except sqlite3.Error:
        raise FileParseError("Not a valid database: '%s'", fname) from None
    

    当上下文被抑制时,内部异常仍然可用,但不会在回溯中打印出来。

    如果您想更详细地了解异常链接的问题,您应该阅读上面链接的 PEP,也许还应该阅读描述 PEP 409 更新实现的 PEP 415

    【讨论】:

    • 对我来说是时光机时刻之一,我没想到会有这么优雅的答案。我建议大家重新阅读What's new in Py3.3,那里有很多好东西:SimpleNamespacefaulthandlervenvpy 在 Windows 上,...
    猜你喜欢
    • 2012-09-14
    • 2014-09-20
    • 1970-01-01
    • 2016-08-20
    • 2011-10-10
    • 2012-06-29
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    相关资源
    最近更新 更多