Python字符串解码问题

Yuv*_*dam 3 python string unicode character-encoding

我试图解析一个包含一些数据的CSV文件,主要是数字但有一些字符串 - 我不知道它们的编码,但我知道它们是希伯来语.

最终我需要知道编码,这样我就可以对字符串进行unicode,打印它们,然后将它们放入数据库中.

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

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

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

知道我怎么能正确解码这些字符串?


编辑:这是一个例子.其中一个字符串看起来像这样(希伯来字母表的前五个字母):

print repr(sampleString)
#prints:
'\xe0\xe1\xe2\xe3\xe4'
Run Code Online (Sandbox Code Playgroud)

(使用Python 2.6.2)

cod*_*ape 12

这就是发生的事情:

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

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

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

print sampleString.decode("cp1255").encode("utf-8")
Run Code Online (Sandbox Code Playgroud)

也可以看看:

一个简单的测试程序,您可以尝试:

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

在我的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
?????
Run Code Online (Sandbox Code Playgroud)

latin-1和ascii的错误消息表示字符串中的unicode字符无法在这些编码中表示.

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

但是当我的utf-8终端以不同于utf-8的编码接收字节时会非常困惑.

在第一种情况下(cp424),我的UTF-8终端显示ABCDE,这意味着A的utf-8表示对应于ה的cp424表示,即字节值65表示utf-8中的A和cp424中的ה.

encode方法有一个可选的字符串参数,您可以使用它来指定当编码不能表示字符时应该发生的事情(文档).支持的策略是严格(默认),忽略,替换,xmlcharref和backslashreplace.您甚至可以添加自己的自定义策略.

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

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

结果:

$ 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'
Run Code Online (Sandbox Code Playgroud)