Skip to main content
 首页 » 编程设计

python之在 Django transaction.atomic() 中捕获并重新引发异常是否可以

2025年02月15日35emanlee

Django 的文档是这样描述transaction.atomic() 和异常的:

https://docs.djangoproject.com/en/1.10/topics/db/transactions/#django.db.transaction.atomic

Avoid catching exceptions inside atomic!

When exiting an atomic block, Django looks at whether it’s exited normally or with an exception to determine whether to commit or roll back. If you catch and handle exceptions inside an atomic block, you may hide from Django the fact that a problem has happened. This can result in unexpected behavior.

This is mostly a concern for DatabaseError and its subclasses such as IntegrityError. After such an error, the transaction is broken and Django will perform a rollback at the end of the atomic block. If you attempt to run database queries before the rollback happens, Django will raise a TransactionManagementError. You may also encounter this behavior when an ORM-related signal handler raises an exception.

The correct way to catch database errors is around an atomic block as shown above. If necessary, add an extra atomic block for this purpose. This pattern has another advantage: it delimits explicitly which operations will be rolled back if an exception occurs.

If you catch exceptions raised by raw SQL queries, Django’s behavior is unspecified and database-dependent.

这样做是否可以,或者这会导致“意外行为”吗?

with transaction.atomic(): 
    # something 
    try: 
        # something 
    except: 
        logger.exception("Report error here.") 
        raise 
     

请您参考如下方法:

根据文档,我会确保重新引发正确的异常,您可以独立处理其他错误。对于 django,只需要在与数据库对话时就出错的事情得到通知。

with transaction.atomic(): 
    # something 
    try: 
        # something 
    except DatabaseError as db_err: 
        logger.exception("Report error here.") 
        raise db_err 
    except Exception: 
        # do something else 
        # no need to reraise 
        # as long as you handle it properly and db integrity is guaranteed