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/中,中文帖子可以成功发布。
最佳答案
tl; dr /快速修复
不要对Willy Nilly进行解码/编码
不要以为您的字符串是UTF-8编码的
尝试在代码中尽快将字符串转换为Unicode字符串
修正您的语言环境:How to solve UnicodeDecodeError in Python 3.6?
不要试图使用快速的reload
hacks
Python 2.x中的Unicode Zen-完整版
在没有看到来源的情况下,很难知道根本原因,因此我将不得不大体讲一下。UnicodeDecodeError: 'ascii' codec can't decode byte
通常在您尝试将包含非ASCII的Python 2.x str
转换为Unicode字符串而未指定原始字符串的编码时发生。
简而言之,Unicode字符串是一种完全独立的Python字符串类型,不包含任何编码。它们仅保存Unicode点代码,因此可以保存整个频谱中的任何Unicode点。字符串包含编码的文本,包括UTF-8,UTF-16,ISO-8895-1,GBK,Big5等。字符串被解码为Unicode,而Unicodes被编码为字符串。文件和文本数据始终以编码的字符串传输。
Markdown模块的作者可能使用unicode()
(抛出异常的地方)作为其余代码的质量门-它会转换ASCII或将现有的Unicode字符串重新包装为新的Unicode字符串。 Markdown作者无法得知传入字符串的编码,因此在传递给Markdown之前,将依赖您将字符串解码为Unicode字符串。
可以使用字符串的u
前缀在代码中声明Unicode字符串。例如。
>>> my_u = u'my ünicôdé strįng'
>>> type(my_u)
<type 'unicode'>
Unicode字符串也可能来自文件,数据库和网络模块。发生这种情况时,您无需担心编码。
陷阱
即使您没有显式调用
str
,也可能发生从unicode()
到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字符串,使用Unicode,然后在输出时编码为
str
。这使您不必担心代码中间的字符串编码。输入/解码
源代码
如果需要将非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文件
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格式返回数据,但是通常需要一些配置。始终对SQL查询使用Unicode字符串。
的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
中返回Unicode。手动地
如果必须手动解码字符串,则只需执行
my_string.decode(encoding)
,其中encoding
是适当的编码。此处提供了Python 2.x支持的编解码器:Standard Encodings。同样,如果得到UnicodeDecodeError
,则可能是编码错误。三明治的肉
像正常strs一样使用Unicode。
输出量
标准输出/打印
print
写入标准输出流。 Python尝试在stdout上配置编码器,以便将Unicode编码为控制台的编码。例如,如果Linux Shell的locale
是en_GB.UTF-8
,则输出将被编码为UTF-8
。在Windows上,您将被限制为8位代码页。错误配置的控制台(例如损坏的语言环境)可能导致意外的打印错误。
PYTHONIOENCODING
环境变量可以强制对stdout进行编码。档案
就像输入一样,
io.open
可用于将Unicode透明地转换为编码的字节字符串。数据库
用于读取的相同配置将允许直接编写Unicode。
Python 3
Python 3不再比Python 2.x更具有Unicode功能,但是在该主题上的混淆却稍少一些。例如,常规
str
现在是Unicode字符串,而旧的str
现在是bytes
。默认编码为UTF-8,因此,如果您在不提供编码的情况下
.decode()
一个字节字符串,Python 3将使用UTF-8编码。这可能解决了50%的人们的Unicode问题。此外,默认情况下
open()
在文本模式下运行,因此返回解码后的str
(Unicode编码)。编码来自您的语言环境,在Un * x系统上通常是UTF-8,在Windows机器上通常是8位代码页,例如Windows-1251。为什么不应该使用
sys.setdefaultencoding('utf8')
这是一个讨厌的黑客(有必要使用
reload
的原因),它只会掩盖问题并阻碍您迁移到Python3.x。理解问题,解决根本原因并享受Unicode zen。有关更多详细信息,请参见Why should we NOT use sys.setdefaultencoding("utf-8") in a py script?
关于python - 如何解决:“UnicodeDecodeError:'ascii'编解码器无法解码字节”,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48757354/