关于python:UnicodeDecodeError:’ascii’编解码器无法解码位置2中的字节0xd1:序号不在范围内(128)

UnicodeDecodeError: 'ascii' codec can't decode byte 0xd1 in position 2: ordinal not in range(128)

我正在尝试使用一个很大的数据集,其中包含一些非标准字符。我需要使用Unicode,根据作业规范,但我感到困惑。(而且很可能做得不对。)

我打开csv时使用:

1
 15     ncesReader = csv.reader(open('geocoded_output.csv', 'rb'), delimiter='\t', quotechar='"')

然后,我尝试用以下代码对其进行编码:

1
name=school_name.encode('utf-8'), street=row[9].encode('utf-8'), city=row[10].encode('utf-8'), state=row[11].encode('utf-8'), zip5=row[12], zip4=row[13],county=row[25].encode('utf-8'), lat=row[22], lng=row[23])

除了lat和lng之外,我对所有东西都进行编码,因为它们需要发送到API。当我运行程序将数据集解析为我可以使用的数据集时,我得到了以下跟踪信息。

1
2
3
4
5
6
7
8
Traceback (most recent call last):
  File"push_into_db.py", line 80, in <module>
    main()
  File"push_into_db.py", line 74, in main
    district_map = buildDistrictSchoolMap()
  File"push_into_db.py", line 32, in buildDistrictSchoolMap
    county=row[25].encode('utf-8'), lat=row[22], lng=row[23])
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd1 in position 2: ordinal not in range(128)

我想我应该告诉你我使用的是python 2.7.2,这是在django 1.4上构建的应用程序的一部分。我读过一些关于这个主题的文章,但似乎没有一篇是直接适用的。任何帮助都将不胜感激。

您可能还想知道导致此问题的一些非标准字符是什么?可能还有。


Unicode不等于UTF-8。后者只是前者的编码。

你这样做是错误的。您正在读取UTF-8编码的数据,因此必须将UTF-8编码的字符串解码为Unicode字符串。

所以只要用.decode替换.encode,它就可以工作(如果.csv是utf-8编码的)。

不过,没什么好羞愧的。我敢打赌,五分之三的程序员一开始很难理解这一点,如果不是更多的话;)

更新:如果您的输入数据不是UTF-8编码的,那么当然,您必须使用适当的编码来.decode()。如果没有给出任何内容,Python将采用ASCII,这显然会在非ASCII字符上失败。


只需将这些行添加到代码中:

1
2
3
import sys
reload(sys)
sys.setdefaultencoding('utf-8')


对于python 3用户。你可以做到

1
2
with open(csv_name_here, 'r', encoding="utf-8") as f:
    #some codes

它也适用于烧瓶:)


错误的主要原因是Python假定的默认编码是ASCII。因此,如果要由encode('utf8')编码的字符串数据包含不在ASCII范围内的字符,例如"hgvcj"????387',python将抛出错误,因为字符串不是预期的编码格式。

如果您使用的是3.5版之前的python版本,一个可靠的解决方案是将python假定的默认编码设置为utf8

1
2
3
4
import sys
reload(sys)
sys.setdefaultencoding('utf8')
name = school_name.encode('utf8')

这样,Python就能够预测字符串中不属于ASCII范围的字符。

但是,如果您使用的是3.5或更高版本的python,那么reload()函数不可用,因此您必须使用decode来修复它,例如。

1
name = school_name.decode('utf8').encode('utf8')


对于python 3用户:

将编码从"ascii"更改为"latin1"有效。

此外,您还可以尝试使用以下代码段读取前10000个字节来自动查找编码:

1
2
3
4
import chardet  
with open("dataset_path", 'rb') as rawdata:  
            result = chardet.detect(rawdata.read(10000))  
print(result)