如何捕获 sqlalchemy 上的特定异常?

Hid*_*ide 6 python sqlalchemy

我想捕获特定的异常,例如UniqueViolationsqlalchemy 上的异常。

但 sqlalchemy 仅通过IntegrityError.

所以我用下面的代码捕获了特定的异常。

except sqlalchemy.exc.IntegrityError as e:
    from psycopg2 import errors
    if isinstance(e.orig, errors.UniqueViolation):
        pass
    elif isinstance(e.orig, errors.ForeignKeyViolation):
        pass
Run Code Online (Sandbox Code Playgroud)

但看起来并不优雅。

我不想使用 if 语句只是捕获特定的异常名称。

有什么办法可以解决这个问题吗?

谢谢。

Sup*_*oot 0

这只是一个想法 - 我根本没有测试过 - 但也许上下文管理器可以做你想做的事。例如,如果您希望特定查询引发原始异常,则使用with raise_orig(): query().

from contextlib import contextmanager
from sqlalchemy.exc import StatementError

@contextmanager
def raise_orig():
    try:
        yield
    except StatementError as stmt_exc:
        raise stmt_exc.orig


def query():
    raise StatementError(
        message="Message from SQLAlchemy",
        statement="SELECT 1",
        params=(),
        orig=RuntimeError("The original exception instance"),
    )


if __name__ == "__main__":
    with raise_orig():
        query()
Run Code Online (Sandbox Code Playgroud)

这是引发的回溯:

Traceback (most recent call last):
  File "raise_orig.py", line 7, in raise_orig
    yield
  File "raise_orig.py", line 23, in <module>
    query()
  File "raise_orig.py", line 17, in query
    orig=RuntimeError("The original exception instance"),
sqlalchemy.exc.StatementError: Message from SQLAlchemy
[SQL: SELECT 1]

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "raise_orig.py", line 23, in <module>
    query()
  File "C:\Users\peter_000\AppData\Local\Programs\Python\Python36\Lib\contextlib.py", line 99, in __exit__
    self.gen.throw(type, value, traceback)
  File "raise_orig.py", line 9, in raise_orig
    raise stmt_exc.orig
RuntimeError: The original exception instance
Run Code Online (Sandbox Code Playgroud)

我选择测试 forStatementError因为这是具有该属性的最主要的异常类型orig

并不完美,因为回溯将比现在更加复杂,但至少应该允许您捕获特定类型。

您还可以使用上下文管理器模式来抽象异常类型检查和处理,这样您就不需要在任何地方重复它(那么它只需要在一个地方看起来很难看!):

Traceback (most recent call last):
  File "raise_orig.py", line 7, in raise_orig
    yield
  File "raise_orig.py", line 23, in <module>
    query()
  File "raise_orig.py", line 17, in query
    orig=RuntimeError("The original exception instance"),
sqlalchemy.exc.StatementError: Message from SQLAlchemy
[SQL: SELECT 1]

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "raise_orig.py", line 23, in <module>
    query()
  File "C:\Users\peter_000\AppData\Local\Programs\Python\Python36\Lib\contextlib.py", line 99, in __exit__
    self.gen.throw(type, value, traceback)
  File "raise_orig.py", line 9, in raise_orig
    raise stmt_exc.orig
RuntimeError: The original exception instance
Run Code Online (Sandbox Code Playgroud)