我正在使用 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/