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;博士/快速修复
不要随意解码/编码
不要假设您的字符串是 UTF-8 编码的
尝试在您的代码中尽快将字符串转换为 Unicode 字符串
修复您的语言环境:如何解决 Python 3.6 中的 UnicodeDecodeError?
不要试图使用快速重新加载技巧
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,Unicode 被编码为字符串。文件和文本数据始终以编码字符串的形式传输。
Markdown 模块的作者可能使用 unicode()
(抛出异常的地方)作为其余代码的质量门——它将转换 ASCII 或将现有的 Unicode 字符串重新包装为新的 Unicode 字符串。 Markdown 作者无法知道传入字符串的编码,因此在传递给 Markdown 之前将依赖您将字符串解码为 Unicode 字符串。
可以使用字符串的 u
前缀在您的代码中声明 Unicode 字符串。例如
>>> my_u = u'my ünicôdé strįng'
>>> type(my_u)
<type 'unicode'>
Unicode 字符串也可能来自文件、数据库和网络模块。发生这种情况时,您无需担心编码。
陷阱
即使您没有显式调用 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: ' + '€'
例子
https://i.stack.imgur.com/uUUBd.jpg
在此图中,使用 ascii
调用 decode()
(这与在没有给定编码的情况下调用 unicode()
相同)。由于 ASCII 不能包含大于 0x7F
的字节,这将引发 UnicodeDecodeError
异常:
https://i.stack.imgur.com/oyk7O.jpg
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。如果 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 格式返回数据,但通常需要一些配置。始终使用 Unicode 字符串进行 SQL 查询。
在连接字符串中添加:
charset='utf8',
use_unicode=True
例如
>>> db = MySQLdb.connect(host="localhost", user='root', passwd='passwd', db='sandbox', use_unicode=True, charset="utf8")
添加:
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 尝试在标准输出上配置编码器,以便将 Unicode 编码为控制台的编码。例如,如果 Linux shell 的 locale
是 en_GB.UTF-8
,则输出将被编码为 UTF-8
。在 Windows 上,您将被限制为 8 位代码页。
错误配置的控制台(例如损坏的语言环境)可能会导致意外的打印错误。 PYTHONIOENCODING
环境变量可以强制标准输出的编码。
文件
就像输入一样,io.open
可用于将 Unicode 透明地转换为编码的字节字符串。
数据库
相同的读取配置将允许直接写入 Unicode。
蟒蛇 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')
这是一个令人讨厌的 hack(您必须使用 reload
是有原因的),它只会掩盖问题并阻碍您迁移到 Python 3.x。了解问题,解决根本原因,享受 Unicode zen。有关详细信息,请参阅 Why should we NOT use sys.setdefaultencoding("utf-8") in a py script?
最后我得到了它:
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
。然后错误不再存在。
str
,所以它不会过期。在 Python 2.x 中,Unicode 处于过渡状态,因此在将字节转换为 Unicode 时假设编码是危险的。因此,Py2 的默认 ASCII 编码是经过深思熟虑的选择,为什么更改默认编码需要重新加载 sys
的故意破解。在 Py2 中消除编码错误的正确方法是在需要转换时明确地将(字节)字符串解码和编码为 Unicode - 而不仅仅是假设字符串是 UTF-8 编码的。
这是经典的“unicode 问题”。我相信解释这一点超出了 StackOverflow 答案的范围,无法完全解释正在发生的事情。
很好解释here。
简而言之,您已将被解释为字节字符串的内容传递给需要将其解码为 Unicode 字符的内容,但默认编解码器 (ascii) 失败。
我向您指出的演示文稿提供了避免这种情况的建议。使您的代码成为“unicode 三明治”。在 Python 2 中,使用 from __future__ import unicode_literals
会有所帮助。
更新:如何修复代码:
好的 - 在你的变量“源”中你有一些字节。从您的问题中不清楚他们是如何进入那里的 - 也许您是从网络表单中阅读的?在任何情况下,它们都不是用 ascii 编码的,但是 python 正在尝试将它们转换为 unicode,假设它们是。您需要明确告诉它编码是什么。这意味着您需要知道编码是什么!这并不总是那么容易,它完全取决于这个字符串的来源。您可以尝试一些常见的编码 - 例如 UTF-8。你告诉 unicode() 编码作为第二个参数:
source = unicode(source, 'utf-8')
currentFile = open(filename, 'rt', encoding='latin1')
或 currentFile = open(filename, 'rt', encoding='utf-8')
- 请参阅此处:stackoverflow.com/a/23917799/2047442
在某些情况下,当您检查默认编码 (print sys.getdefaultencoding()
) 时,它会返回您正在使用 ASCII。如果您更改为 UTF-8,它将不起作用,具体取决于您的变量的内容。我找到了另一种方法:
import sys
reload(sys)
sys.setdefaultencoding('Cp1252')
reload(sys)
用于该特定原因。
我正在寻找解决以下错误消息:
unicodedecodeerror:“ascii”编解码器无法解码位置 5454 中的字节 0xe2:序数不在范围内(128)
我终于通过指定“编码”来修复它:
f = open('../glove/glove.6B.100d.txt', encoding="utf-8")
希望它也能帮助你。
"UnicodeDecodeError: 'ascii' codec can't decode byte"
此错误的原因:input_string 必须是 unicode 但给出了 str
"TypeError: Decoding Unicode is not supported"
此错误的原因:尝试将 unicode input_string 转换为 unicode
因此,首先检查您的 input_string 是否为 str
并在必要时转换为 unicode:
if isinstance(input_string, str):
input_string = unicode(input_string, 'utf-8')
其次,上面只是改变了类型,但没有删除非 ascii 字符。如果要删除非 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')
为了在 Ubuntu 安装中在操作系统级别解决此问题,请检查以下内容:
$ locale charmap
如果你得到
locale: Cannot set LC_CTYPE to default locale: No such file or directory
代替
UTF-8
然后像这样设置 LC_CTYPE
和 LC_ALL
:
$ export LC_ALL="en_US.UTF-8"
$ export LC_CTYPE="en_US.UTF-8"
我发现最好的办法是始终转换为 unicode - 但这很难实现,因为在实践中,您必须检查每个参数并将其转换为您编写的每个函数和方法,包括某种形式的字符串处理。
所以我想出了以下方法来保证 unicodes 或字节字符串,从任一输入。简而言之,include and use 以下 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))
这里还有一些reasoning about this。
print unicode(u'Zürich', encoding="UTF-8")
然后抱怨“但令人惊讶的是,您无法将 unicode ext 编码为 UTF8”。 unicode()
不编码;它会解码,而您无法解码 Unicode - 它已经解码了!
得到了同样的错误,这解决了我的错误。谢谢! python 2 和 python 3 在 unicode 处理方面的不同使得腌制文件很难加载。所以使用 python pickle 的编码参数。当我尝试从我的 python 3.7 打开腌制数据时,下面的链接帮助我解决了类似的问题,而我的文件最初保存在 python 2.x 版本中。 https://blog.modest-destiny.com/posts/python-2-and-3-compatible-pickle-save-and-load/ 我在脚本中复制了 load_pickle 函数,并在加载 input_data 时调用了 load_pickle(pickle_file),如下所示:
input_data = load_pickle("my_dataset.pkl")
load_pickle 函数在这里:
def load_pickle(pickle_file):
try:
with open(pickle_file, 'rb') as f:
pickle_data = pickle.load(f)
except UnicodeDecodeError as e:
with open(pickle_file, 'rb') as f:
pickle_data = pickle.load(f, encoding='latin1')
except Exception as e:
print('Unable to load data ', pickle_file, ':', e)
raise
return pickle_data
load_pickle
函数的定义。
Encode 将 unicode 对象转换为字符串对象。我认为您正在尝试对字符串对象进行编码。首先将您的结果转换为 unicode 对象,然后将该 unicode 对象编码为“utf-8”。例如
result = yourFunction()
result.decode().encode('utf-8')
这对我有用:
file = open('docs/my_messy_doc.pdf', 'rb')
我遇到了同样的错误,URL 包含非 ascii 字符(值 > 128 的字节),我的解决方案:
url = url.decode('utf8').encode('utf-8')
注意:utf-8、utf8 只是别名。仅使用“utf8”或“utf-8”应该以相同的方式工作
就我而言,在 Python 2.7 中为我工作,我想这个赋值改变了 str
内部表示中的“某些东西”——即,它强制在 url
中正确解码支持的字节序列,最后将字符串放入一个 utf-8 str
,所有的魔法都在正确的位置。 Python 中的 Unicode 对我来说是黑魔法。希望有用
我遇到了同样的问题,但它不适用于 Python 3。我遵循了这个,它解决了我的问题:
enc = sys.getdefaultencoding()
file = open(menu, "r", encoding = enc)
您必须在读取/写入文件时设置编码。
我对字符串“PastelerÃa Mallorca”遇到了同样的问题,我解决了:
unicode("PastelerÃa Mallorca", 'latin-1')
简而言之,为了确保在 Python 2 中正确处理 unicode:
使用 io.open 读取/写入文件
使用 from __future__ import unicode_literals
配置其他数据输入/输出(例如,数据库、网络)以使用 unicode
如果您无法将输出配置为 utf-8,请为它们转换输出 print(text.encode('ascii', 'replace').decode())
有关说明,请参阅 @Alastair McCormack 的 detailed answer。
io.open(path, 'r', encoding='utf-8')
读取 utf-8 编码的文件。
在 Django (1.9.10)/Python 2.7.5 项目中,我经常遇到 UnicodeDecodeError
异常;主要是当我尝试将 unicode 字符串提供给日志记录时。我为任意对象创建了一个辅助函数,基本上格式化为 8 位 ascii 字符串,并将表中没有的任何字符替换为“?”。我认为这不是最好的解决方案,但由于默认编码是 ascii (我不想改变它)它会做:
def encode_for_logging(c, encoding='ascii'): if isinstance(c, basestring): return c.encode(encoding, 'replace') elif isinstance(c, Iterable): c_ = [] for v in c: c_.append(encode_for_logging(v, encoding)) return c_ else: return encode_for_logging(unicode(c))
当我们的字符串中有一些非 ASCII 字符并且我们在没有正确解码的情况下对该字符串执行任何操作时,就会发生此错误。这帮助我解决了我的问题。我正在读取一个 CSV 文件,其中包含列 ID、文本和解码字符,如下所示:
train_df = pd.read_csv("Example.csv")
train_data = train_df.values
for i in train_data:
print("ID :" + i[0])
text = i[1].decode("utf-8",errors="ignore").strip().lower()
print("Text: " + text)
这是我的解决方案,只需添加编码。 with open(file, encoding='utf8') as f
并且因为读取 glove 文件会花费很长时间,所以我建议将 glove 文件转换为 numpy 文件。当您在 netx time 读取嵌入权重时,它将节省您的时间。
import numpy as np
from tqdm import tqdm
def load_glove(file):
"""Loads GloVe vectors in numpy array.
Args:
file (str): a path to a glove file.
Return:
dict: a dict of numpy arrays.
"""
embeddings_index = {}
with open(file, encoding='utf8') as f:
for i, line in tqdm(enumerate(f)):
values = line.split()
word = ''.join(values[:-300])
coefs = np.asarray(values[-300:], dtype='float32')
embeddings_index[word] = coefs
return embeddings_index
# EMBEDDING_PATH = '../embedding_weights/glove.840B.300d.txt'
EMBEDDING_PATH = 'glove.840B.300d.txt'
embeddings = load_glove(EMBEDDING_PATH)
np.save('glove_embeddings.npy', embeddings)
要点链接:https://gist.github.com/BrambleXu/634a844cdd3cd04bb2e3ba3c83aef227
在 Python 文件的顶部指定:# encoding=utf-8,它应该可以解决问题
我在使用 Python2.7 时遇到了这个错误。它在尝试运行许多 python 程序时发生在我身上,但我设法用这个简单的脚本重现了它:
#!/usr/bin/env python
import subprocess
import sys
result = subprocess.Popen([u'svn', u'info'])
if not callable(getattr(result, "__enter__", None)) and not callable(getattr(result, "__exit__", None)):
print("foo")
print("bar")
成功时,它应该打印出 'foo' 和 'bar',如果您不在 svn 文件夹中,可能还会显示错误消息。
失败时,它应该打印“UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 39: ordinal not in range(128)”。
在尝试重新生成我的语言环境和此问题中发布的许多其他解决方案后,我了解到错误正在发生,因为我的 PATH 环境变量中编码了一个特殊字符 (ĺ)。在 '~/.bashrc' 中修复 PATH 并退出我的会话并再次进入后(显然采购 '~/.bashrc' 不起作用),问题就消失了。
不定期副业成功案例分享
io.open
读取/写入文件,使用from __future__ import unicode_literals
,将其他数据输入/输出(例如,数据库)配置为使用 unicode。PYTHONIOENCODING=utf-8
。如果这不能解决问题,您需要联系脚本的作者来修复他们的代码。