Python/Flask:UnicodeDecodeError/UnicodeEncodeError:“ascii”编解码器无法解码/编码

Posted

技术标签:

【中文标题】Python/Flask:UnicodeDecodeError/UnicodeEncodeError:“ascii”编解码器无法解码/编码【英文标题】:Python/Flask: UnicodeDecodeError/ UnicodeEncodeError: 'ascii' codec can't decode/encode 【发布时间】:2017-03-01 06:55:27 【问题描述】:

很抱歉关于这个问题的第 100 万个问题,但我已经阅读了很多关于这个主题的内容,但仍然没有修复这个错误(所有这些都是新手)。 我正在尝试使用烧瓶(使用 Ubuntu 16.04/python 2.7.12)在网站上显示 postgres 表的内容。表中有非 ascii 字符(本例中为“ü”),结果为 UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 2: ordinal not in range(128)。

这就是我的 init.py 的样子:

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

from flask import Blueprint, render_template
import psycopg2
from .forms import Form
from datetime import datetime
from .table import Item, ItemTable

test = Blueprint('test', __name__)

def init_test(app):
    app.register_blueprint(test)

def createTable(cur):
    cmd = "select * from table1 order by start desc;"
    cur.execute(cmd)
    queryResult = cur.fetchall()
    items = []
    table = 'table could not be read'
    if queryResult is not None:         
        for row in range(0, len(queryResult)):
        items.append(Item(queryResult[row][0], queryResult[row][1].strftime("%d.%m.%Y"), queryResult[row][2].strftime("%d.%m.%Y"), \
                          queryResult[row][1].strftime("%H:%M"), queryResult[row][2].strftime("%H:%M"), \
                          queryResult[row][3], queryResult[row][4], queryResult[row][5], queryResult[row][6]))
        table = ItemTable(items)
    return table


@test.route('/test')
def index():
    dbcon = psycopg2.connect("dbname=testdb user=postgres host=localhost")
    cur = dbcon.cursor()
    table = createTable(cur)
    cur.close()
    return render_template('test_index.html', table=table)

以及部分 html 文件:

% extends "layout.html" %
% block head %Title% endblock %
% block body %
<script type="text/javascript" src=" url_for('static', filename='js/bootstrap.js') "></script>
<link rel="stylesheet" type="text/css" href=" url_for('static', filename='css/custom.css') ">
<div class="row" id="testid">
    table
</div>
% endblock %#
Local Variables:
coding: utf-8
End: #

问题出在 queryResult[row][6] 中,它是表中唯一带字符串的行,其余的是整数。 postgres 数据库的编码是 utf-8。 queryResult[row][6] 的类型返回类型“str”。我读到的here 是字符串应该以utf-8 编码,因为那是数据库客户端的编码。好吧,这似乎不起作用!? 然后我添加了这一行

psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)

强制结果为 unicode(queryResult[row][6] 的类型返回类型 'unicode'),因为正如推荐的 here,我试图在任何地方都坚持使用 unicode。这导致了 UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc' in position 2: ordinal not in range(128)。 然后我想,可能之前转换为字符串(字节)出了点问题,然后我尝试自己做,然后写

queryResult[row][6].encode('utf-8', 'replace')

导致 UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 2: ordinal not in range(128).甚至没有使用“忽略”而不是“替换”。 这里发生了什么?我通过创建和传递变量 v=u'ü' 检查了 render_template() 是否存在 unicode 问题,但这没问题并且显示正确。是的,我阅读了通常推荐的内容,例如 nedbatchelder.com/text/unipain.html 和 Unicode Demystified,但这并没有帮助我解决我的问题,我显然遗漏了一些东西。

这是第一个 UnicodeDecodeError 的回溯:

File "/home/name/Desktop/testFlask/venv/lib/python2.7/site-packages/flask/app.py", line 2000, in __call__
return self.wsgi_app(environ, start_response)
File "/home/name/Desktop/testFlask/venv/lib/python2.7/site-packages/flask/app.py", line 1991, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/home/name/Desktop/testFlask/venv/lib/python2.7/site-packages/flask/app.py", line 1567, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/name/Desktop/testFlask/venv/lib/python2.7/site-packages/flask/app.py", line 1988, in wsgi_app
response = self.full_dispatch_request()
File "/home/name/Desktop/testFlask/venv/lib/python2.7/site-packages/flask/app.py", line 1641, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/name/Desktop/testFlask/venv/lib/python2.7/site-packages/flask/app.py", line 1544, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/name/Desktop/testFlask/venv/lib/python2.7/site-packages/flask/app.py", line 1639, in full_dispatch_request
rv = self.dispatch_request()
File "/home/name/Desktop/testFlask/venv/lib/python2.7/site-packages/flask/app.py", line 1625, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/name/Desktop/testFlask/app/test/__init__.py", line 95, in index
return render_template('test_index.html', table=table) #, var=var
File "/home/name/Desktop/testFlask/venv/lib/python2.7/site-packages/flask/templating.py", line 134, in render_template
context, ctx.app)
File "/home/name/Desktop/testFlask/venv/lib/python2.7/site-packages/flask/templating.py", line 116, in _render
rv = template.render(context)
File "/home/name/Desktop/testFlask/venv/lib/python2.7/site-packages/jinja2/environment.py", line 989, in render
return self.environment.handle_exception(exc_info, True)
File "/home/name/Desktop/testFlask/venv/lib/python2.7/site-packages/jinja2/environment.py", line 754, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/name/Desktop/testFlask/app/templates/test_index.html", line 1, in top-level template code
% extends "layout.html" %
File "/home/name/Desktop/testFlask/app/templates/layout.html", line 40, in top-level template code
% block body %% endblock %
File "/home/name/Desktop/testFlask/app/templates/test_index.html", line 7, in block "body"
table
File "/home/name/Desktop/testFlask/venv/lib/python2.7/site-packages/flask_table/table.py", line 86, in __html__
tbody = self.tbody()
File "/home/name/Desktop/testFlask/venv/lib/python2.7/site-packages/flask_table/table.py", line 103, in tbody
out = [self.tr(item) for item in self.items]
File "/home/name/Desktop/testFlask/venv/lib/python2.7/site-packages/flask_table/table.py", line 120, in tr
''.join(c.td(item, attr) for attr, c in self._cols.items()
File "/home/name/Desktop/testFlask/venv/lib/python2.7/site-packages/flask_table/table.py", line 121, in <genexpr>
if c.show))
File "/home/name/Desktop/testFlask/app/test/table.py", line 7, in td
self.td_contents(item, self.get_attr_list(attr)))
File "/home/name/Desktop/testFlask/venv/lib/python2.7/site-packages/flask_table/columns.py", line 99, in td_contents
return self.td_format(self.from_attr_list(item, attr_list))
File "/home/name/Desktop/testFlask/venv/lib/python2.7/site-packages/flask_table/columns.py", line 114, in td_format
return Markup.escape(content)
File "/home/name/Desktop/testFlask/venv/lib/python2.7/site-packages/markupsafe/__init__.py", line 165, in escape
rv = escape(s)

非常感谢任何帮助...

【问题讨论】:

【参考方案1】:

由于在 Python 2 中不强制执行字节码,因此可能会与它们混淆。 据我所知,编码和解码从字符串到字节码和反向工作。因此,如果您的结果集是一个字符串,则无需再次对其进行编码。 如果您对“§”等特殊字符的表示错误,我会尝试这样的事情:

repr(queryResult[row][6])).

这行得通吗?

【讨论】:

如果我将 'repr(queryResult[row][6]))' 传递给 Item(),错误确实消失了。但是现在变音符号在表格中显示为'\xc3\xbc',不可读。当我另外设置 'psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)' 时,我有 u'\xfc',它也不可读。 分别添加 .decode('utf-8') 或 .encode('utf-8')在 repr() 中也不会改变任何事情。知道如何以这种方式显示变音符号吗?谢谢!【参考方案2】:

见:https://wiki.python.org/moin/UnicodeEncodeError

postgres 数据库的编码是 utf-8。 queryResult[row][6] 的类型返回类型“str”。

到目前为止,您已经做对了。请记住,在 Python 2.7 中,str 是一串字节。所以你从数据库中得到了一串字节,可能看起来像'gl\xc3\xbce' ('glüe')。

接下来发生的是程序的某些部分在您的字符串上调用.decode,但使用默认的“ascii”编解码器。它可能是 Item() API 的某些部分需要字符串作为 unicode 对象,或者可能是 Flask 本身。无论哪种方式,您都需要自己在字符串上调用 .decode,因为您知道它实际上是 utf-8:

col_6 = queryResult[row][6].decode('utf-8')
Item(..., ..., col_6, ...)

然后,您将为所有下游 API 提供 unicode,这显然是他们想要的。

我记得是这样的:Unicode 是一种抽象,其中所有内容都表示为“代码点”。如果我们想创建可以在屏幕上打印或作为 HTML 文件发送的真实字节,我们需要对字节进行编码。如果你有一些字节,它们可能意味着任何字母,谁知道呢?您需要对神秘字节进行解码才能获得 Unicode。

希望这会有所帮助。

【讨论】:

不幸的是,这仍然会产生一个 UnicodeEncodeError: 'ascii' 编解码器无法在位置 2 对字符 u'\xfc' 进行编码:序数不在范围内 (128)。任何想法为什么? (请注意:不要按 Enter 换行...)【参考方案3】:

所以我在到处都坚持unicode之后,终于在

的帮助下找到了解决办法
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)

然后这个错误把我带到了我自己写的类 customCol(Col):

class customCol(Col):
def td(self, item, attr):
    return '<td><div id="beschrCol"></div></td>'.format(
        self.td_contents(item, self.get_attr_list(attr)))

这里的问题是.format()调用,看了this之后,我只是把.format前面的字符串转成unicode,问题就解决了,

def td(self, item, attr):
    return u'<td><div id="beschrCol"></div></td>'.format...

也可以将字符串传递给 Item(),但后来我不得不放

queryResult[row][6].decode('utf-8')

在 Item() 调用中。

【讨论】:

以上是关于Python/Flask:UnicodeDecodeError/UnicodeEncodeError:“ascii”编解码器无法解码/编码的主要内容,如果未能解决你的问题,请参考以下文章

python flask怎么指定端口启动

python Python Flask WSGI路由技术#python #flask #wsgi

python Python Flask WSGI路由技术#python #flask #wsgi

python flask 基础入门

Python Flask学习

python flask 报错求助