尝试使用SQLAlchemy捕获完整性错误

Los*_*oul 17 python sqlalchemy pyramid

我在尝试捕获错误时遇到问题.我正在使用Pyramid/SQLAlchemy并使用电子邮件作为主键创建了一个注册表单.问题是当输入重复的电子邮件时它会引发IntegrityError,所以我试图捕获该错误并提供一条消息,但无论我做什么我都抓不到它,错误不断出现.

try:
    new_user = Users(email, firstname, lastname, password)
    DBSession.add(new_user)
    return HTTPFound(location = request.route_url('new'))
except IntegrityError:
    message1 = "Yikes! Your email already exists in our system. Did you forget your password?"
Run Code Online (Sandbox Code Playgroud)

当我尝试时,我得到了同样的信息except exc.SQLAlchemyError(虽然我想捕捉到特定的错误而不是全部捕获).我也试过exc.IntegrityError但没有运气(虽然它存在于API中).

我的Python语法有什么问题,或者我需要在SQLAlchemy中做些什么才能捕获它?


我不知道如何解决这个问题,但我对可能导致问题的原因有一些想法.也许try语句没有失败但是成功,因为SQLAlchemy本身就引发了异常而Pyramid正在生成视图,因此except IntegrityError:永远不会被激活.或者,更有可能的是,我完全错误地抓住了这个错误.

Mic*_*kel 21

在Pyramid中,如果您已配置会话(脚手架自动为您执行)以使用该ZopeTransactionExtension会话,则在视图执行之前,会话不会被刷新/提交.如果要在视图中自己捕获任何SQL错误,则需要强制a flush将SQL发送到引擎.DBSession.flush()应该在之后做add(...).

更新

我正在使用保存点的示例更新此答案,因为关于如何使用事务包执行此操作的示例非常少.

def create_unique_object(db, max_attempts=3):
    while True:
        sp = transaction.savepoint()
        try:
            obj = MyObject()
            obj.identifier = uuid.uuid4().hex
            db.add(obj)
            db.flush()
        except IntegrityError:
            sp.rollback()
            max_attempts -= 1
            if max_attempts < 1:
                raise
        else:
            return obj

obj = create_unique_object(DBSession)
Run Code Online (Sandbox Code Playgroud)

请注意,如果不使用表级锁定,即使这很容易在事务之间重复,但它至少显示了如何使用保存点.


ast*_*asr 8

你需要做的是捕获一般异常并输出它的类; 那么你可以使异常更具体.

except Exception as ex:
    print ex.__class__
Run Code Online (Sandbox Code Playgroud)

  • 不,我说他可以用它来实际确定异常的类 - 然后捕获正确的类. (5认同)
  • 为什么?他试图捕获特定的异常,我不明白为什么你建议捕获一般异常? (2认同)

jfs*_*jfs 5

直到有可能是没有数据库操作DBSession.commit()因此IntegrityError在已控制器代码之后堆栈后来提高try/except已经返回。