【问题标题】:Encoding error with sqlalchemy and postgresqlsqlalchemy 和 postgresql 的编码错误
【发布时间】:2013-01-24 20:44:43
【问题描述】:

我正在将金字塔用于具有 postgres 数据库、wtforms、sqlalchemy 和 jinja2 的 Web 应用程序,当应用程序尝试从数据库中获取问题类型以使用 wtforms 填充选择字段时出现此错误:

Error: 'ascii' codec can't decode byte 0xc3 in position 5: ordinal not in range(128)

这是model.py中的问题类型表:

class Mixin(object):
    id = Column(Integer, primary_key=True, autoincrement=True)
    created = Column(DateTime())
    modified = Column(DateTime())

    __table_args__ = {
        'mysql_engine': 'InnoDB',
        'mysql_charset': 'utf8'
    }
    __mapper_args__ = {'extension': BaseExtension()}

class IssueType(Mixin, Base):
    __tablename__ = "ma_issue_types"
    name = Column(Unicode(40), nullable=False)

    def __init__(self, name):
        self.name = name

进入 bd 我有这个:

# select name from ma_issue_types where id = 3;
name    
------------
Teléfono

这是发生错误的部分

# -*- coding: utf-8 -*-

from issuemall.models import DBSession, IssueType


class IssueTypeDao(object):

    def getAll(self):
        dbsession = DBSession()
        return dbsession.query(IssueType).all() #HERE THROWS THE ERROR

这是回溯

Traceback (most recent call last):
  File "/issueMall/issuemall/controller/issueRegisterController.py", line 16, in issue_register
    form = IssueRegisterForm(request.POST)
  File "/env/lib/python2.7/site-packages/wtforms/form.py", line 178, in __call__
    return type.__call__(cls, *args, **kwargs)
  File "/env/lib/python2.7/site-packages/wtforms/form.py", line 224, in __init__
    super(Form, self).__init__(self._unbound_fields, prefix=prefix)
  File "/env/lib/python2.7/site-packages/wtforms/form.py", line 39, in __init__
    field = unbound_field.bind(form=self, name=name, prefix=prefix, translations=translations)
  File "/env/lib/python2.7/site-packages/wtforms/fields/core.py", line 301, in bind
    return self.field_class(_form=form, _prefix=prefix, _name=name, _translations=translations, *self.args, **dict(self.kwargs, **kwargs))
  File "/issueMall/issuemall/form/generalForm.py", line 11, in __init__
    types = issueTypeDao.getAll()
  File "/issueMall/issuemall/dao/master/issueTypeDao.py", line 11, in getAll
    return self.__dbsession.query(IssueType).all()
  File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/query.py", line 2115, in all
    return list(self)
  File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/query.py", line 2341, in instances
    fetch = cursor.fetchall()
  File "build/bdist.linux-x86_64/egg/sqlalchemy/engine/base.py", line 3205, in fetchall
    l = self.process_rows(self._fetchall_impl())
  File "build/bdist.linux-x86_64/egg/sqlalchemy/engine/base.py", line 3172, in _fetchall_impl
    return self.cursor.fetchall()
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 5: ordinal not in range(128)

我尝试了这个,但它不起作用 ascii as default encoding in python

我尝试了类似的方法,但没有成功

gae python ascii codec cant decode byte

return dbsession.query(IssueType.id, IssueType.name.encode('utf-8')).all() #or decode('utf-8')

【问题讨论】:

  • 那是一大堆代码。您能否尝试进一步本地化您的问题,并编辑我们的问题以使其更易于处理?
  • 错误在这里 return dbsession.query(IssueType).all()
  • 不,这就是错误的表现。我的意思是尝试调试东西,看看最后调用了什么,看看使用ascii解码了什么,为什么?
  • 就在这一行,错误显示返回 dbsession.query(IssueType).all() 直到此时唯一发生的事情是调用函数而不传递参数,因为它获得了表的所有记录
  • 在您使用DBSession 之前,它一定已经接到了DBSession.configure(bind=engine) 之类的电话或类似的电话(除非我混淆了框架)。当然engine 有一个encoding='utf-8',但请你仔细检查一下吗?

标签: python postgresql encoding sqlalchemy


【解决方案1】:

您需要配置 Psycopg2 的客户端编码。见SQLAlchemy documentation

默认情况下,psycopg2 驱动程序使用 psycopg2.extensions.UNICODE 扩展名,这样 DBAPI 可以直接接收和返回所有字符串作为 Python Unicode 对象 - SQLAlchemy 将这些值传递给原样。此处的 Psycopg2 将根据当前的“客户端编码”设置对字符串值进行编码/解码;默认情况下,这是postgresql.conf 文件中的值,通常默认为SQL_ASCII。通常,这可以更改为 utf-8,作为更有用的默认值:

#client_encoding = sql_ascii # actually, defaults to database
                             # encoding
client_encoding = utf8

影响客户端编码的第二种方法是在本地 Psycopg2 中设置它。 SQLAlchemy 将根据使用client_encoding 参数传递给create_engine() 的值在所有新连接上调用psycopg2 的set_client_encoding() 方法(参见:http://initd.org/psycopg/docs/connection.html#connection.set_client_encoding):

engine = create_engine("postgresql://user:pass@host/dbname", client_encoding='utf8')

这会覆盖 Postgresql 客户端配置中指定的编码。

client_encoding 参数可以指定为引擎 URL 中的查询字符串:

 postgresql://user:pass@host/dbname?client_encoding=utf8

【讨论】:

  • 非常感谢,解决办法是修改postgresql.conf中的编码
  • 你也可以设置postgresql://user:pass@host/dbname?client_encoding=utf8
【解决方案2】:

我使用 mysql 并像这样设置字符集。它对我有用。

from sqlalchemy import create_engine
from sqlalchemy.engine.url import URL

db_url = {
    'database': 'db_name',
    'drivername': 'mysql',
    'username': 'username',
    'password': 'mypassword',
    'host': '127.0.0.1',
    'query': {'charset': 'utf8'},
}

engine = create_engine(URL(**db_url), encoding="utf8")

【讨论】:

    猜你喜欢
    • 2016-07-13
    • 1970-01-01
    • 2021-09-03
    • 2011-11-02
    • 2023-03-09
    • 1970-01-01
    • 2015-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多