繁体   English   中英

Python - “ascii”编解码器无法解码字节

[英]Python - 'ascii' codec can't decode byte

我真的很困惑。 我试图编码,但错误说can't decode...

>>> "你好".encode("utf8")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)

我知道如何避免字符串上带有“u”前缀的错误。 我只是想知道为什么在调用 encode 时错误是“无法解码”。 Python 在幕后做了什么?

"你好".encode('utf-8')

encode将 unicode 对象转换为string对象。 但是在这里您已经在string对象上调用了它(因为您没有 u)。 所以python必须首先将string转换为unicode对象。 所以它相当于

"你好".decode().encode('utf-8')

但是解码失败,因为字符串不是有效的 ascii。 这就是为什么您会抱怨无法解码的原因。

始终从 unicode编码为字节。
在这个方向上,您可以选择 encoding

>>> u"你好".encode("utf8")
'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> print _
你好

另一种方法是从字节解码为 un​​icode。
在这个方向上,您必须知道编码是什么

>>> bytes = '\xe4\xbd\xa0\xe5\xa5\xbd'
>>> print bytes
你好
>>> bytes.decode('utf-8')
u'\u4f60\u597d'
>>> print _
你好

这一点再怎么强调也不为过。 如果您想避免玩 unicode “whack-a-mole”,那么了解数据级别发生的事情很重要。 这里用另一种方式解释:

  • 一个 unicode 对象已经被解码了,你永远不想在它上面调用decode
  • 一个字节串对象已经被编码,你永远不想在它上面调用encode

现在,在字节字符串上看到.encode时,Python 2 首先尝试将其隐式转换为文本(一个unicode对象)。 类似地,在 unicode 字符串上看到.decode时,Python 2 会隐式地尝试将其转换为字节(一个str对象)。

这些隐式转换是您在调用encode时会得到Unicode Decode Error原因。 这是因为 encoding 通常接受一个unicode类型的参数; 当接收到str参数时,在用另一种编码重新编码之前,会隐式解码为unicode类型的对象。 此转换选择默认的 'ascii' 解码器 ,为您提供编码器内的解码错误。

事实上,在 Python 3 中str.decodebytes.encode方法甚至不存在。 他们的移除是为了避免这种常见的混淆[有争议]。

...或任何编码sys.getdefaultencoding()提到的; 通常这是“ascii”

你可以试试这个

import sys
reload(sys)
sys.setdefaultencoding("utf-8")

要么

您也可以尝试以下

在 .py 文件顶部添加以下行。

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

如果您使用的是 Python < 3,则需要通过在它前面加上u来告诉解释器您的字符串文字是 Unicode

Python 2.7.2 (default, Jan 14 2012, 23:14:09) 
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> "你好".encode("utf8")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
>>> u"你好".encode("utf8")
'\xe4\xbd\xa0\xe5\xa5\xbd'

进一步阅读Unicode HOWTO

您使用u"你好".encode('utf8')对 unicode 字符串进行编码。 但是如果你想代表"你好" ,你应该解码它。 就像:

"你好".decode("utf8")

你会得到你想要的。 也许您应该了解更多有关编码和解码的信息。

如果您正在处理 Unicode,有时代替encode('utf-8') ,您也可以尝试忽略特殊字符,例如

"你好".encode('ascii','ignore')

或如这里所建议的something.decode('unicode_escape').encode('ascii','ignore')

在此示例中不是特别有用,但在无法转换某些特殊字符的其他情况下可以更好地工作。

或者,您可以考虑使用replace()替换特定字符

如果您从 Linux 或类似系统(BSD,不确定 Mac)上的 shell 启动 python 解释器,您还应该检查 shell 的默认编码。

从 shell(不是 python 解释器)调用locale charmap ,你应该看到

[user@host dir] $ locale charmap
UTF-8
[user@host dir] $ 

如果不是这种情况,并且您会看到其他内容,例如

[user@host dir] $ locale charmap
ANSI_X3.4-1968
[user@host dir] $ 

Python 将(至少在某些情况下,例如在我的情况下)继承 shell 的编码,并且将无法打印(某些?全部?)unicode 字符。 在这种情况下,您通过sys.getdefaultencoding()sys.setdefaultencoding()看到和控制的 Python 自己的默认编码将被忽略。

如果你发现你有这个问题,你可以通过

[user@host dir] $ export LC_CTYPE="en_EN.UTF-8"
[user@host dir] $ locale charmap
UTF-8
[user@host dir] $ 

(或者选择您想要的任何键映射而不是 en_EN。)您还可以编辑/etc/locale.conf (或管理系统中区域设置的任何文件)来更正此问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM