postgresql - 异常中的 SQLAlchemy Unicode 问题

标签 postgresql unicode sqlalchemy python-2.x

我正在使用 postgres/SQLAlchemy/Flask-Admin 开发 Flask 应用程序。但是,在 Admin 界面中,由于 unicode(exc) 引发 UnicodeDecodeError,因此无法报告任何包含 Unicode 字母的数据库错误。

我能够将该问题定位到 sqlalchemy.exc

class StatementError(SQLAlchemyError):
    ...
    def __unicode__(self):
        return self.__str__()

并重现问题:

class A(Base):
    __tablename__="a"
    id = Column(Integer, primary_key=True)
    name = Column(String)
    name2 = Column(String, nullable=False)

session = Session()
a = A(name=u"עברית")
session.add(a)

try:
    session.commit()
except Exception as e:
    print(repr(e))
    print("------------------")
    print(unicode(e))

哪个返回:

ProgrammingError('(psycopg2.ProgrammingError) column "name" of relation "a" does not exist\nLINE 1: INSERT INTO a (name, name2) VALUES (\'\xd7\xa2\xd7\x91\xd7\xa8\xd7\x99\xd7\xaa\', NULL) RETURNING...\n                       ^\n',)
------------------
Traceback (most recent call last):
  File "test.py", line 27, in <module>
    print(unicode(e))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd7 in position 118: ordinal not in range(128)

我目前通过用从 utf-8 解码的类替换相关异常来解决它。然而,这是一个糟糕的 hack,我正在寻找一个合适的解决方案:

  • 有没有办法配置 SQLAlchemy 自动解码收到的错误消息?
  • 有没有办法配置 Postgres 以 latin 编码输出消息(不太受欢迎,但可以接受)
  • 有没有办法让 unicode 尝试用 utf-8 而不是 ascii/latin 解码?
  • 有什么办法可以解决吗???

(该问题仅与 Python2 有关。在 Python3 中,上面的代码有效。我相信这是因为默认编码是 utf-8)

最佳答案

我实际上认为从您的应用程序中修补 SQLAlchemy 是正确的合理干净的解决方案。原因如下:

  • 您已经确定了一些通常被认为是 SQLAlchemy 中的错误的东西。

  • 您可以编写一个补丁,该补丁在 SQLAlchemy 当前使用的所有情况下都表现相同。也就是说,您的补丁不会破坏现有代码

  • 即使 SQLAlchemy 已修复,您的补丁也无害的可能性非常高。

  • 进行此更改可以减少整个代码中 SQLAlchemy 错误对解决方案的影响,例如更改可能打印异常的每个地方。

  • 将 PostGres 更改为返回 latin1 编码实际上无济于事,因为 python 使用的是 ascii 编码,这在给定 latin1 字符串时会产生相同的错误。此外,更改 PostGres 以返回 latin1 错误可能会涉及更改连接编码;这可能会给 unicode 数据带来问题。

这是一个简单的程序,可以修补 sqlalchemy.exc.StatementError 并测试补丁。如果您愿意,您甚至可以尝试生成一个包含 unicode 的异常,将其转换为 unicode,并且仅在引发 UnicodeDecodeError 时才应用补丁。如果这样做,当 sqlalchemy 修复问题时,您的补丁将自动停止应用。

# -*- coding: utf-8 -*-
from sqlalchemy.exc import StatementError

def statement_error_unicode(self):
    return unicode(str(self), 'utf-8')
# See <link to sqlalchemy issue>; can be removed once we require a
# version of sqlalchemy with a fix to that issue
StatementError.__unicode__ = statement_error_unicode

message = u'Sqlalchemy unicode 😞'
message_str = message.encode('utf-8')
error = StatementError(message_str, 'select * from users', tuple(), '')
print unicode(error)

关于postgresql - 异常中的 SQLAlchemy Unicode 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43566704/

相关文章:

postgresql - 为什么我的 Web 应用程序使用 ipv6 连接到本地 postgres

sql - 如何删除两列中的重复值并仅获取 Postgresql 中的特定值

delphi - 为什么Delphi2009+中的SizeOf(Char) = 2?

python - 这是内存泄漏吗(python 中带有 sqlalchemy/sqlite 的程序)

python - 如何在 Flask SQLAlchemy 中使数据库关系与辅助反向引用双向工作?

python - 根据数据库验证 MySQL 的最快方法

postgresql - 在一个命令中选择或插入一行

ruby-on-rails - rails + Postgis : error cannot drop table spatial_ref_sys

python - 使用装饰器将所有 Unicode 字符串转换为二进制字符串是一种好习惯吗?

python - 多语言 .py 文件的编码