如何解决:“UnicodeDecodeError:'ascii'编解码器无法解码字节”
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的静态博客应用程序中,中文文章可以成功发布。 比如这个应用程序: http : //github.com/vrypan/bucket3 。 在我的网站http://bc3.brite.biz/中 ,中文文章可以成功发布。
最后我明白了:
 as3:/usr/local/lib/python2.7/site-packages# cat sitecustomize.py # encoding=utf8 import sys reload(sys) sys.setdefaultencoding('utf8') 
让我检查一下:
 as3:~/ngokevin-site# python Python 2.7.6 (default, Dec 6 2013, 14:49:02) [GCC 4.4.5] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> reload(sys) <module 'sys' (built-in)> >>> sys.getdefaultencoding() 'utf8' >>> 
 以上显示了python的默认编码是utf8 。 那么错误是没有更多。 
TL;博士
- 不要解码/编码威利
- 不要以为你的string是UTF-8编码的
- 尝试在您的代码中尽快将string转换为Unicodestring
Python 2.x – 长版本
没有看到源头,很难知道根本原因,所以我必须一般地讲。
  UnicodeDecodeError: 'ascii' codec can't decode byte当您尝试将包含非ASCII的Python 2.x str转换为Unicodestring而不指定原始string的编码时, UnicodeDecodeError: 'ascii' codec can't decode byte 。 
简而言之,Unicodestring是一个完全独立的Pythonstring,不包含任何编码。 它们只保存Unicode 点代码 ,因此可以保存整个频谱的任何Unicode点。 string包含编码的文本,比如UTF-8,UTF-16,ISO-8895-1,GBK,Big5等。 string被解码为Unicode , Unicodes被编码为string 。 文件和文本数据总是以编码的string传输。
  Markdown模块的作者可能使用unicode() (其中抛出exception)作为其余代码的质量门 – 它将转换ASCII或将现有的Unicodesstring重新包装为新的Unicodestring。  Markdown作者无法知道传入string的编码,所以在传递给Markdown之前,将依赖于将string解码为Unicodestring。 
  Unicodestring可以在您的代码中使用string的u前缀来声明。 例如 
 >>> my_u = u'my ünicôdé strįng' >>> type(my_u) <type 'unicode'> 
Unicodestring也可能来自文件,数据库和networking模块。 发生这种情况时,您不必担心编码。
陷阱
 即使不显式调用unicode()也可能会发生从str到Unicode的转换。 
 以下情况会导致UnicodeDecodeErrorexception: 
 unicode('€') # explicit conversion without encoding u"The currency is: {}".format('€') # new style format string into Unicode string - Python will try to convert value string to Unicode first u'The currency is: %s' % '€' # old style format string into Unicode string - Python will try to convert value string to Unicode first u'The currency is: ' + '€' # append string to Unicode - Python will try to convert string to Unicode first 
例子
 在下图中,您可以看到词café是如何根据terminaltypes以“UTF-8”或“Cp1252”编码进行编码的。 在这两个例子中, caf只是一般的ascii。 在UTF-8中,使用两个字节进行编码。 在“Cp1252”中,é是0xE9(这也恰好是Unicode点值(这不是巧合))。 正确的decode()被调用,并且转换成Python Unicode是成功的:  
 
 在这个图中, decode()是用ascii调用的(这与调用unicode()没有给定的编码相同)。 由于ASCII不能包含大于0x7F字节,这将引发一个UnicodeDecodeErrorexception: 
  
 
Unicode三明治
在代码中形成一个Unicode三明治是一个很好的做法,在这里你将所有传入的数据解码为Unicodestring,与Unicodes一起工作,然后在出门时编码。 这样可以避免担心代码中间的string编码问题。
input/解码
源代码
 如果您需要在源代码中烘焙非ASCII字符,只需在string前加u即可创buildUnicodestring。 例如 
 u'Zürich' 
为了允许Python解码你的源代码,你需要添加一个编docker来匹配文件的实际编码。 例如,如果您的文件编码为“UTF-8”,则可以使用:
 # encoding: utf-8 
只有在源代码中使用非ASCII码时才有必要。
档
 通常从文件接收非ASCII数据。  io模块提供了一个TextWrapper,可以使用给定的encodingdynamic解码文件。 您必须使用正确的编码文件 – 它不能被轻易猜出。 例如,对于一个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。 如果来自read()行的UnicodeDecodeError ,那么你可能使用了错误的编码值。 
CSV文件
Python 2.7 CSV模块不支持非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返回数据,但通常需要一些configuration。 始终使用Unicodestring进行SQL查询。
MySQL的
在连接string中添加:
 charset='utf8', use_unicode=True 
PostgreSQL的
加:
 psycopg2.extensions.register_type(psycopg2.extensions.UNICODE) psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY) 
HTTP
 网页可以用任何编码进行编码。  Content-type头应该包含一个charset字段来提示编码。 内容然后可以手动解码这个值。 或者, Python-Requests在response.text返回Unicodes。 
手动
 如果您必须手动解码string,则可以简单地执行my_string.decode(encoding) ,其中encoding是适当的编码。  Python 2.x支持的编解码器在这里给出: 标准编码 。 再次,如果你得到UnicodeDecodeError那么你可能得到了错误的编码。 
三明治的肉
像普通strs一样使用Unicodes。
产量
标准输出/打印
  print通过标准输出stream写入。  Python试图在stdout上configuration一个编码器,以便Unicode编码为控制台的编码。 例如,如果Linux shell的locale是en_GB.UTF-8 ,则输出将被编码为UTF-8 。 在Windows上,您将被限制为8位代码页。 
 configuration不正确的控制台(如损坏的区域设置)可能会导致意外的打印错误。  PYTHONIOENCODING环境variables可以强制stdout的编码。 
档
 就像input一样, io.open可以用来将Unicodes透明地转换为编码的字节串。 
数据库
读取相同的configuration将允许Unicodes直接写入。
Python 3
  Python 3没有更多的Unicode能够像Python 2.x一样,但是常规的str现在是一个Unicodestring,旧的str现在是bytes 。 
 缺省编码现在是UTF-8,所以如果你在不给出编码的情况下解码.decode()一个字节string,Python 3使用UTF-8编码。 这大概解决了50%的人的Unicode问题。 
 此外, open()默认在文本模式下运行,因此返回解码的str (Unicode)。 编码是从您的语言环境派生而来的,这些语言环境通常在Un * x系统上是UTF-8,或者在Windows上是8位代码页,例如windows-1251。 
这是经典的“unicode问题”。 我相信解释这是超出了StackOverflow答案的范围,以完全解释发生了什么。
这里很好的解释。
在非常简短的总结中,你已经将一些被解释为字节串的东西传递给需要将其解码为Unicode字符的东西,但是默认编解码器(ascii)失败。
我指出你提供的build议是为了避免这个问题。 让你的代码成为“unicode三明治”。 在Python 2中,使用“from __future__ import unicode_literals”有帮助。
更新:如何修复代码:
好的 – 在你的variables“source”中你有一些字节。 从你的问题来看,他们是如何进入的 – 也许你是从networking表单读取的? 在任何情况下,它们都不用ascii编码,但python试图将它们转换为unicode,假设它们是。 你需要明确地告诉它编码是什么。 这意味着你需要知道什么是编码! 这并不总是很容易,而且完全取决于这个string是从哪里来的。 您可以尝试一些常见的编码 – 例如UTF-8。 你把unicode()的编码告诉第二个参数:
 source = unicode(source, 'utf-8') 
 在某些情况下,当你检查你的默认编码( print sys.getdefaultencoding() )时,它返回你正在使用的ASCII。 如果您更改为UTF-8,则它不起作用,具体取决于variables的内容。 我发现另一种方式: 
 import sys reload(sys) sys.setdefaultencoding('Cp1252') 
这个错误主要是因为你的上下文需要一个unicodestring,但是传递的只是一个string。 在你转换成代码检查之前,如果string已经在unicode,在这种情况下,你将得到一个TypeError:解码Unicode不支持,因为你试图转换成unicode一个string已经在unicode。在你转换为下面:
  if isinstance(input_string, str): input_string = unicode(input_string, 'utf-8') 
在上面添加,上面不删除不支持的字符。 它只是改变types,但非ascii仍然存在。 为了删除下面的字符,
  if isinstance(input_string, str): input_string = input_string.decode('ascii', 'ignore').encode('ascii') #note: this removes the character and encodes back to string. elif isinstance(input_string, unicode): input_string = input_string.encode('ascii', 'ignore') 
我发现最好的办法是始终转换为unicode – 但这很难实现,因为在实践中,您必须检查每个参数并将其转换为您编写的每个函数和方法,包括某种forms的string处理。
所以我想出了以下方法,以保证unicodes或字节string,从任何input。 总之, 包括并使用以下lambda:
 # guarantee unicode string _u = lambda t: t.decode('UTF-8', 'replace') if isinstance(t, str) else t _uu = lambda *tt: tuple(_u(t) for t in tt) # guarantee byte string in UTF8 encoding _u8 = lambda t: t.encode('UTF-8', 'replace') if isinstance(t, unicode) else t _uu8 = lambda *tt: tuple(_u8(t) for t in tt) 
例子:
 text='Some string with codes > 127, like Zürich' utext=u'Some string with codes > 127, like Zürich' print "==> with _u, _uu" print _u(text), type(_u(text)) print _u(utext), type(_u(utext)) print _uu(text, utext), type(_uu(text, utext)) print "==> with u8, uu8" print _u8(text), type(_u8(text)) print _u8(utext), type(_u8(utext)) print _uu8(text, utext), type(_uu8(text, utext)) # with % formatting, always use _u() and _uu() print "Some unknown input %s" % _u(text) print "Multiple inputs %s, %s" % _uu(text, text) # but with string.format be sure to always work with unicode strings print u"Also works with formats: {}".format(_u(text)) print u"Also works with formats: {},{}".format(*_uu(text, text)) # ... or use _u8 and _uu8, because string.format expects byte strings print "Also works with formats: {}".format(_u8(text)) print "Also works with formats: {},{}".format(*_uu8(text, text)) 
这里有一些更多的推理 。
编码将一个unicode对象转换为一个string对象。 我想你正在尝试编码一个string对象。 首先将您的结果转换为unicode对象,然后将该unicode对象编码为“utf-8”。 例如
  result = yourFunction() result.decode().encode('utf-8') 
我遇到了同样的问题,string“PasteleràMallorca”,我解决了:
 unicode("PastelerÃa Mallorca", 'latin-1') 
我有同样的问题,但它不适用于Python 3.我遵循这一点,它解决了我的问题:
 enc = sys.getdefaultencoding() file = open(menu, "r", encoding = enc) 
在读取/写入文件时,必须设置编码。
 在Django(1.9.10)/ Python 2.7.5项目中,我频繁出现UnicodeDecodeErrorexception; 主要是当我尝试提供unicodestringlogging。 我为任意对象做了一个辅助函数,基本上格式化为8位asciistring,并将不在表中的任何字符replace为'?'。 我认为这不是最好的解决scheme,但由于默认编码是ascii(我不想改变它),它会做: 
 def encode_for_logging(c,encoding ='ascii'):
    如果isinstance(c,basestring):
        返回c.encode(编码,'replace')
     elif isinstance(c,Iterable):
         c_ = []
         for v in c:
             c_.append(encode_for_logging(v,encoding))
        返回c_
    其他:
        返回encode_for_logging(unicode(c))
`
添加python文件的顶部。 这将转换您的代码文件为Unicode这不会修复所有的情况下。 但是这个代码和我很多次相同
 # -*- coding:utf-8 -*-