Python字符串解码问题

标签 python string unicode character-encoding

我正在尝试解析包含一些数据的 CSV 文件,主要是数字,但也有一些字符串——我不知道它们的编码,但我知道它们是希伯来语。

最终我需要知道编码,以便我可以对字符串进行统一编码、打印它们,并可能稍后将它们放入数据库中。

我尝试使用 Chardet ,它声称字符串是 Windows-1255 (cp1255) 但尝试执行 print someString.decode('cp1255') 会产生臭名昭著的错误:

UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-4: ordinal not in range(128)

我尝试了所有可能的其他编码,但无济于事。此外,该文件绝对有效,因为我可以在 Excel 中打开 CSV 文件并看到正确的数据。

知道如何正确解码这些字符串吗?


编辑:这是一个例子。其中一个字符串如下所示(希伯来字母表的前五个字母):

print repr(sampleString)
#prints:
'\xe0\xe1\xe2\xe3\xe4'

(使用 Python 2.6.2)

最佳答案

这是正在发生的事情:

  • sampleString是字节串(cp1255编码)
  • sampleString.decode("cp1255") 将字节串解码(decode==bytes -> unicode 字符串)为unicode字符串
  • print sampleString.decode("cp1255") 尝试将 unicode 字符串打印到标准输出。 Print 必须对 unicode 字符串进行编码(encode==unicode string -> bytes)。您看到的错误意味着 python print 语句无法将给定的 unicode 字符串写入控制台的编码。 sys.stdout.encoding 是终端的编码。

所以问题是你的控制台不支持这些字符。您应该能够调整控制台以使用另一种编码。如何执行此操作的详细信息取决于您的操作系统和终端程序。

另一种方法是手动指定要使用的编码:

print sampleString.decode("cp1255").encode("utf-8")

另见:

您可以试验的简单测试程序:

import sys
print sys.stdout.encoding
samplestring = '\xe0\xe1\xe2\xe3\xe4'
print samplestring.decode("cp1255").encode(sys.argv[1])

在我的 utf-8 终端上:

$ python2.6 test.py utf-8
UTF-8
אבגדה

$ python2.6 test.py latin1
UTF-8
Traceback (most recent call last):
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 0-4: ordinal not in range(256)

$ python2.6 test.py ascii
UTF-8
Traceback (most recent call last):
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-4: ordinal not in range(128)

$ python2.6 test.py cp424
UTF-8
ABCDE

$ python2.6 test.py iso8859_8
UTF-8
�����

latin-1 和 ascii 的错误消息意味着字符串中的 unicode 字符无法用这些编码表示。

注意最后两个。我将 unicode 字符串编码为 cp424 和 iso8859_8 编码(http://docs.python.org/library/codecs.html#standard-encodings 中列出的两种支持希伯来字符的编码)。我使用这些编码没有异常(exception),因为希伯来语 unicode 字符在编码中有表示。

但是当我的 utf-8 终端接收到编码与 utf-8 不同的字节时,它会变得非常困惑。

第一种情况(cp424),我的UTF-8终端显示的是ABCDE,意思是A的utf-8表示对应的是UTF-8的CP424表示,即字节值65表示UTF-8中的A,UTF-8中的UTF-8表示cp424.

encode 方法有一个可选的字符串参数,您可以使用它来指定当编码不能表示字符 (documentation) 时应该发生什么。支持的策略有 strict(默认)、ignore、replace、xmlcharref 和 backslashreplace。你甚至可以 add your own custom strategies .

另一个测试程序(我在字符串周围加上引号以更好地显示忽略行为):

import sys
samplestring = '\xe0\xe1\xe2\xe3\xe4'
print "'{0}'".format(samplestring.decode("cp1255").encode(sys.argv[1], 
      sys.argv[2]))

结果:

$ python2.6 test.py latin1 strict
Traceback (most recent call last):
  File "test.py", line 4, in <module>
    sys.argv[2]))
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 0-4: ordinal not in range(256)
[/tmp]
$ python2.6 test.py latin1 ignore
''
[/tmp]
$ python2.6 test.py latin1 replace
'?????'
[/tmp]
$ python2.6 test.py latin1 xmlcharrefreplace
'&#1488;&#1489;&#1490;&#1491;&#1492;'
[/tmp]
$ python2.6 test.py latin1 backslashreplace
'\u05d0\u05d1\u05d2\u05d3\u05d4'

关于Python字符串解码问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2389410/

相关文章:

python - Unicode 编码错误 Python - 解析 XML 无法编码字符 (Star)

php - 日本/中国电子邮件地址?

python - 如何使用鼠标手动放置 networkx 节点?

c - 当我为它们分配不同的值时,为什么这两个字符串打印相同的值?

java - 为什么我在这里得到一个找不到文件的异常?

python - os.walk 返回不同编码的非 ascii (unicode) 文件名,如何处理?

python - Django HttpRequest 与请求

python - Python 中的 SMBus/I2C 在请求读取时不断触发接收回调

python - 在执行 pandas.DataFrame.groupby().sum() 时保留非数字列

java - Java字符串定义中的 "escape sequence"是什么意思?