UnicodeDecodeError:'ascii'编解码器无法解码位置2中的字节0xd1:序数不在范围内(128)

时间:2012-05-02 00:17:09

标签: python django utf-8

我正在尝试使用一个非常大的数据集,其中包含一些非标准字符。根据工作规范,我需要使用unicode,但我很困惑。 (并且很可能做错了。)

我使用以下方式打开CSV

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

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

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。当我运行程序将数据集解析为我可以使用的程序时,我得到以下Traceback。

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上构建应用程序的一部分。我已经阅读了几个关于这个主题的帖子,但似乎都没有直接适用。任何帮助将不胜感激。

您可能还想知道导致此问题的一些非标准字符是Ñ并且可能是É。

10 个答案:

答案 0 :(得分:135)

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

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

因此,只需将.encode替换为.decode,它就可以正常工作(如果.csv是UTF-8编码的话)。

但是,没有什么可以感到羞耻的。我敢打赌,五分之三的程序员在开始理解这个问题时遇到了麻烦,如果不是更多的话;)

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

答案 1 :(得分:73)

只需将此行添加到您的代码中:

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

答案 2 :(得分:14)

适用于Python 3用户。你可以做到

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

它也适用于烧瓶:)

答案 3 :(得分:8)

错误的主要原因是python假定的默认编码是ASCII。 因此,如果要由:app编码的字符串数据包含在ASCII范围之外的字符,例如对于像'hgvcj터파크387'这样的字符串,python会抛出错误,因为字符串不是预期的编码格式。

如果您使用的是早于3.5版的python版本,可靠的修复方法是将python假定的默认编码设置为encode('utf8')

utf8

这样python就可以预测字符串中超出ASCII范围的字符。

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

import sys
reload(sys)
sys.setdefaultencoding('utf8')
name = school_name.encode('utf8')

答案 4 :(得分:1)

对于Python 3用户:

更改&#39; ascii&#39;到了拉丁1&#39;的工作原理。

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

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

答案 5 :(得分:0)

由于纬度和经度而以编码UTF 16打开。 使用open(csv_name_here,'r',encoding =“ utf-16”)as f:

答案 6 :(得分:0)

如果在创建或续订证书时运行certbot时遇到此问题,请使用以下方法

grep -r -P '[^\x00-\x7f]' /etc/apache2 /etc/letsencrypt /etc/nginx

该命令在注释的一个.conf文件中找到了令人反感的字符“´”。删除它(您可以根据需要编辑评论)并重新加载nginx之后,一切又恢复了。

来源:https://github.com/certbot/certbot/issues/5236

答案 7 :(得分:0)

我的计算机的语言环境设置错误。

我先做了

>>> import locale
>>> locale.getpreferredencoding(False)
'ANSI_X3.4-1968'

locale.getpreferredencoding(False)open() when you don't provide an encoding调用的函数。输出应为'UTF-8',但在这种情况下为variant of ASCII

然后我运行bash命令locale并获得了输出

$ locale
LANG=
LANGUAGE=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=

TL; DR:我使用的是默认的Ubuntu语言环境,这会导致Python以ASCII而不是UTF-8格式打开文件。我不得不set my localeen_US.UTF-8

sudo apt install locales && sudo locale-gen en_US en_US.UTF-8    
sudo dpkg-reconfigure locales

答案 8 :(得分:0)

或者当您使用Python处理文本(如果它是Unicode文本)时,请注意它是Unicode。

设置text=u'unicode text'而不是text='unicode text'

这对我来说很有效。

答案 9 :(得分:0)

仅通过将参数“ rb”读为二进制而不是“ r”读来工作