【发布时间】:2021-09-10 06:39:50
【问题描述】:
我有一个小型 Python Web 应用程序(用 Flask 编写),它使用 sqlalchemy 将数据持久保存到数据库中。当我尝试插入重复行时,会引发异常,如下所示:
(psycopg2.errors.UniqueViolation) duplicate key value violates unique constraint "uix_my_column"
我想包装异常并重新引发我自己的,这样我就可以添加自己的日志记录和特定于该特定错误的消息传递。这是我尝试过的(简化):
from db import DbApi
from my_exceptions import BadRequest
from psycopg2.errors import UniqueViolation # <-- this does not exist!
class MyClass:
def __init__(self):
self.db = DbApi()
def create(self, data: dict) -> MyRecord:
try:
with self.db.session_local(expire_on_commit=False) as session:
my_rec = MyRecord(**data)
session.add(my_rec)
session.commit()
session.refresh(my_rec)
return my_rec
except UniqueViolation as e:
raise BadRequest('A duplicate record already exists')
但这无法捕获错误,因为 psycopg2.errors.UniqueViolation 实际上不是类名 (!)。
在 PHP 中,这就像捕获复制/粘贴异常的类名一样简单,但在 Python 中,这更加模糊。
有一个类似的问题here,但它没有处理这个特定的用例并且(重要的是)它没有阐明如何识别根异常类名称。
如何找出实际引发的异常? Python 为什么要隐藏这个?
【问题讨论】:
-
Sqlalchemy 包装了底层的 dbapi 错误,所以你需要捕获 sqlalchemy 错误,而不是 dbapi 错误,然后你可以通过 SQLAlchemy 来检查原始错误。
-
我最近也回答了这个相关的问题:stackoverflow.com/a/57766555/6560549
-
谢谢。但是,我仍然不清楚如何识别我试图捕获的原始异常的类名。谷歌搜索 psycopg2 文档是找出引发什么异常的唯一方法吗?为什么这在 Python 中不更透明?
-
已尽力在下面的答案中解释,很高兴详细说明那里的任何观点,请在 cmets 中询问。
标签: python sqlalchemy