如何修复:UnicodeDecodeError:'编解码器无法解码字节(&Q;) [英] How to fix: "UnicodeDecodeError: 'ascii' codec can't decode byte"

查看:21
本文介绍了如何修复:UnicodeDecodeError:'编解码器无法解码字节(&Q;)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

as3:~/ngokevin-site# nano content/blog/20140114_test-chinese.mkd
as3:~/ngokevin-site# wok
Traceback (most recent call last):
File "/usr/local/bin/wok", line 4, in
Engine()
File "/usr/local/lib/python2.7/site-packages/wok/engine.py", line 104, in init
self.load_pages()
File "/usr/local/lib/python2.7/site-packages/wok/engine.py", line 238, in load_pages
p = Page.from_file(os.path.join(root, f), self.options, self, renderer)
File "/usr/local/lib/python2.7/site-packages/wok/page.py", line 111, in from_file
page.meta['content'] = page.renderer.render(page.original)
File "/usr/local/lib/python2.7/site-packages/wok/renderers.py", line 46, in render
return markdown(plain, Markdown.plugins)
File "/usr/local/lib/python2.7/site-packages/markdown/init.py", line 419, in markdown
return md.convert(text)
File "/usr/local/lib/python2.7/site-packages/markdown/init.py", line 281, in convert
source = unicode(source)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 1: ordinal not in range(128). -- Note: Markdown only accepts unicode input!

如何修复它?

在其他一些基于Python的静态博客应用中,可以成功发布中文帖子。 比如这个APP:http://github.com/vrypan/bucket3。在我的网站http://bc3.brite.biz/中,可以成功发布中文帖子。

推荐答案

tl;DR/快速修复

  • 不要随意解码/编码
  • 不要假设您的字符串是UTF-8编码的
  • 尝试在代码中尽快将字符串转换为Unicode字符串
  • 修复您的区域设置:How to solve UnicodeDecodeError in Python 3.6?
  • 不要使用快速reload黑客

Python2.x中的Unicode Zen-长版本

看不到源头就很难知道根本原因,所以我只能笼统地说一说。

UnicodeDecodeError: 'ascii' codec can't decode byte通常在您尝试将包含非ASCII的Python2.xstr转换为Unicode字符串而不指定原始字符串的编码时发生。

简而言之,Unicode字符串是一种完全独立的不包含任何编码的Python字符串类型。它们只包含Unicode点编码,因此可以包含整个频谱中的任何Unicode点。字符串包含编码文本、Beit UTF-8、UTF-16、ISO-8895-1、GBK、Big5等。字符串解码为UnicodeUnicodes编码为字符串。文件和文本数据始终以编码字符串形式传输。

Markdown模块作者可能使用unicode()(抛出异常的地方)作为其余代码的质量关口-它将转换ASCII或将现有的Unicodes字符串重新包装为新的Unicode字符串。Markdown作者无法知道传入字符串的编码,因此在传递给Markdown之前,将依赖您将字符串解码为Unicode字符串。

可以在代码中使用字符串前缀u声明Unicode字符串。例如

>>> my_u = u'my ünicôdé strįng'
>>> type(my_u)
<type 'unicode'>
Unicode字符串也可能来自文件、数据库和网络模块。发生这种情况时,您无需担心编码问题。

Gotchas

即使您没有显式调用unicode(),也可能发生从str到Unicode的转换。

以下情况会导致UnicodeDecodeError异常:

# Explicit conversion without encoding
unicode('€')

# New style format string into Unicode string
# Python will try to convert value string to Unicode first
u"The currency is: {}".format('€')

# Old style format string into Unicode string
# Python will try to convert value string to Unicode first
u'The currency is: %s' % '€'

# Append string to Unicode
# Python will try to convert string to Unicode first
u'The currency is: ' + '€'         

示例

在下图中,您可以看到单词café是如何根据终端类型以"UTF-8"或"Cp1252"编码的。在这两个例子中,caf只是普通的ascii。在UTF-8中,é使用两个字节进行编码。在"Cp1252"中,é是0xE9(它恰好也是Unicode点值(这不是巧合))。调用了正确的decode(),并且成功转换为Python Unicode:

在此图中,decode()是用ascii调用的(与不带编码的调用unicode()相同)。由于ASCII不能包含大于0x7F的字节,这将引发UnicodeDecodeError异常:

Unicode三明治

在代码中形成Unicode三明治是一种很好的做法,您可以将所有传入数据解码为Unicode字符串,使用Unicodes,然后在输出时编码为。这使您不必担心代码中间的字符串编码问题。

输入/解码

源代码

如果需要在源代码中加入非ASCII,只需在字符串前面加上u即可创建Unicode字符串。例如

u'Zürich'

要允许Python对源代码进行解码,您需要添加一个编码头以匹配文件的实际编码。例如,如果您的文件编码为‘UTF-8’,您可以使用:

# encoding: utf-8

仅当源代码中包含非ASCII时才需要

文件

通常从文件接收非ASCII数据。io模块提供了一个TextWrapper,它使用给定的encoding动态地解码您的文件。您必须对文件使用正确的编码--它不容易被猜到。例如,对于UTF-8文件:

import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
     my_unicode_string = my_file.read() 

my_unicode_string将适合传递到Markdown。如果UnicodeDecodeError来自read()行,则您可能使用了错误的编码值。

CSV文件

Python2.7CSV模块不支持非ASCII字符😩。不过,https://pypi.python.org/pypi/backports.csv的帮助近在咫尺。

像上面一样使用它,但将打开的文件传递给它:

from backports import csv
import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
    for row in csv.reader(my_file):
        yield row

数据库

大多数Python数据库驱动程序可以返回Unicode格式的数据,但通常需要进行一些配置。始终使用Unicode字符串进行SQL查询。

MySQL

在连接字符串中添加:

charset='utf8',
use_unicode=True

例如

>>> db = MySQLdb.connect(host="localhost", user='root', passwd='passwd', db='sandbox', use_unicode=True, charset="utf8")
PostgreSQL

添加:

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

HTTP

网页几乎可以用任何编码进行编码。Content-type标头应包含charset字段以提示编码。然后可以根据该值手动对内容进行解码。或者,Python-Requests返回response.text中的Unicodes。

手动

如果必须手动解码字符串,只需执行my_string.decode(encoding),其中encoding是适当的编码。这里给出了支持Python2.x的编解码器:Standard Encodings。同样,如果您得到UnicodeDecodeError,那么您可能得到了错误的编码。

三明治中的肉

像使用普通STR一样使用Unicodes。

输出

标准输出/打印

print通过标准输出流写入。Python尝试在stdout上配置编码器,以便将Unicodes编码为控制台的编码。例如,如果Linux外壳的localeen_GB.UTF-8,则输出将编码为UTF-8。在Windows上,您将被限制为8位代码页。

错误配置的控制台(如损坏的区域设置)可能会导致意外的打印错误。PYTHONIOENCODING环境变量可以强制对标准输出进行编码。

文件

就像输入一样,io.open可用于将Unicodes透明地转换为编码的字节字符串。

数据库

相同的读取配置将允许直接写入Unicode。

Python3

Python3并不比Python2.x具有更强的Unicode能力,但是它在这个主题上没有那么令人困惑。例如,常规的str现在是Unicode字符串,而旧的str现在是bytes

默认编码是UTF-8,因此如果您.decode()是一个没有给出编码的字节字符串,则Python3将使用UTF-8编码。这可能解决了50%的人的Unicode问题。

此外,open()默认情况下以文本模式操作,因此返回已解码的str(Unicode One)。编码源自您的区域设置,在un*x系统上通常是UTF-8,在Windows系统上通常是8位代码页,如Windows-1251。

为什么不应该使用sys.setdefaultencoding('utf8')

这是一个令人讨厌的黑客攻击(您必须使用reload是有原因的),它只会掩盖问题并阻碍您迁移到Python3.x。了解问题,解决问题的根本原因,享受Unicode禅宗。 有关详细信息,请参阅Why should we NOT use sys.setdefaultencoding("utf-8") in a py script?

这篇关于如何修复:UnicodeDecodeError:&#39;编解码器无法解码字节(&Q;)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆