【问题标题】:Why am I getting an sqlalchemy.exc.ProgrammingError rather than a sqlalchemy.exc.IntegrityError?为什么我收到 sqlalchemy.exc.ProgrammingError 而不是 sqlalchemy.exc.IntegrityError?
【发布时间】:2017-01-02 12:54:51
【问题描述】:

我正在编写一些帐户创建代码并尝试捕获特定的 sqlalchemy 异常,以便在用户使用已与现有帐户关联的电子邮件注册帐户时反馈适当的错误消息。

当这种情况发生时,我原以为会得到一个 IntegrityError,但我却得到了一个 ProgrammingError。我可以很高兴地捕捉 ProgrammingError ,但我试图理解为什么我没有得到我所期望的。

为了清晰起见,我已经删减了模型和代码,但模型看起来像:

from service import db
from sqlalchemy import Index

class UserProfile(db.Model):
user_id = db.Column(db.String(255), nullable=False, primary_key=True)
email = db.Column(db.String(255), nullable=False)

def __init__(self, account_data):
    self.user_id = account_data['userId']
    self.email = account_data['email'].lower()

def __repr__(self):
    return 'UserID-{}, Email-{}'.format(self.user_id,self.email)                                                                            

Index('idx_email', UserProfile.email, unique=True)

代码的主要部分如下所示:

@app.route('/create_account', methods=['POST'])
def create_account():

account_data = request.get_json()

account_details = UserProfile(account_data)
try:
    db.session.add(account_details)
    db.session.flush()

    # do stuff

    db.session.commit()

except ProgrammingError as err:
    db.session.rollback()
    if "duplicate key value violates unique constraint \"idx_email\"" in str(err):
        LOGGER.error('Email address already in use!'

所以如果我在一些 json 中发布例如:

{
  "userId": "Fred", 
  "email": "a@b.com"
}

然后使用不同的 userId 但相同的电子邮件再次发布:

{
  "userId": "Bob", 
  "email": "a@b.com"
}

我预计第二个帖子会引发 IntegrityError,但我看到它引发了 ProgrammingError:

sqlalchemy.exc.ProgrammingError: (pg8000.core.ProgrammingError)
('ERROR', 
 '23505', 
 'duplicate key value violates unique constraint "idx_email"', 
 'Key (email)=(a@b.com) already exists.', 
 'public', 
 'user_profile', 
 'idx_email',  
 'nbtinsert.c', 
 '406', 
 '_bt_check_unique', '', '') 
[SQL: 'INSERT INTO user_profile (user_id, email) VALUES (%s, %s)']
[parameters: ('Bob', 'a@b.com')]

我错过了什么?

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    不幸的是,当涉及到DBAPI 错误时,SQLAlchemy 只是包装了底层 dbapi 兼容库引发的异常。

    也就是说,SQLAlchemy 只提出了一个ProgrammingError因为pg8000 选择了提出一个ProgrammingError

    如果您一直使用psycopg2 来管理您的底层连接,那么您的错误将表现为IntegrityError(如预期的那样)。

    根据pg8000 documentation,它永远不会引发IntegrityError。事实上,它不会引发以下任何问题:

    • 完整性错误;
    • 数据错误;
    • 数据库错误;
    • 操作错误;

    这里的教训是,当涉及到数据库级别的错误时,您无法保证 SQLAlchemy 将在不同的 dbapi 连接器之间抛出的类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-03
      • 2018-07-01
      • 2017-06-18
      相关资源
      最近更新 更多