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


107

我正在尝试使用其中包含一些非标准字符的超大型数据集。根据工作规范,我需要使用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上构建的应用程序的一部分。我已经阅读了有关此主题的几篇文章,但似乎没有一篇直接适用。任何帮助将不胜感激。

您可能还想知道导致问题的一些非标准字符是Ñ,甚至是É。


1
您的原始文件编码是什么?我认为您应该根据原始编码对其进行解码,然后转换为utf 8
肖啸2012年

Answers:


152

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

您做错了方法。您正在读取 UTF-8 编码的数据,因此必须将UTF-8编码的字符串解码为unicode字符串。

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

没什么可羞耻的。我敢打赌,五分之三的程序员最初很难理解这一点,如果不是更多的话;)

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


1
错误的原因是Python试图自动从默认编码ASCII对其进行解码,以便随后可以按照他指定的方式将其编码为UTF-8。由于数据不是有效的ASCII,因此无法正常工作。
2012年

7
当然可以,但是如果它是UTF8 编码的数据(如我所猜),那.decode('utf-8')该怎么做,不是吗?
ch3ka 2012年

当然,您可能是对的。我只是在解释为什么在这种情况下会出现该特定错误。
2012年

1
完善!非常感谢你。原来是.decode('latin-1'),这很有意义,因为是Ñ导致了我的问题。再次!谢谢!
jelkimantis 2012年

您的解决方案在某些情况下有效,但是如果我使用此解决方案,那么我会收到另一个错误'ascii'编解码器,无法在位置2编码字符u'\ xf1':序数不在范围内(128)
Vikash Mishra

84

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

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

5
`AttributeError:模块'sys'没有属性'setdefaultencoding'在Python 3中似乎不起作用
skjerns

呜呜呜!这对我有帮助。
Shougo Makishima

1
它适用于我的Python 2.7,请注意,需要reload(sys),否则,将无法访问setdefaultencoding。
Yu Shen

1
那是使它在许多SO问题中对我有用的唯一原因。非常感谢!
Freedo

名称'reload'未定义
Davide

28

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

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

它也可以与烧瓶一起工作:)


1
这是我第一次帮助某人通过这里。知道我帮助了我感觉很好:)
Skrmnghrd

1
您也帮助了我:)所有其他答案均不适用于文件读取。现在,我需要找出如何解决它,也可以用于写作;)
user2194898

可以给我发送代码链接吗?我会尽力帮助
Skrmnghrd

9

错误的主要原因是python假定的默认编码为ASCII。因此,如果要编码的字符串数据encode('utf8')包含ASCII范围之外的字符(例如,类似“ hgvcj터파크387”的字符串),则python将抛出错误,因为该字符串未采用预期的编码格式。

如果您使用的Python版本早于3.5版,则可靠的解决方法是将python假定的默认编码设置为utf8

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

这样,python就能预见ASCII范围之外的字符串中的字符。

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

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

您的答案和我的答案有什么区别
khelili miliana

1
更详细。人们经常发现因果关系细节很有帮助。顺便说一句,您的代码可以正常工作,没有任何减损的意图。
Temi Fakunle '17

1
reload在Python 3中可用,您只需导入它即可。从imp导入重新加载
喵喵

@Meow,但是Python 3中没有sys.setdefaultencoding。因此,在兼容py2 \ py3的情况下,可以进行一些检查,也许是sys.getdefaultencoding()。希望能就此事提出一些建议。stackoverflow.com/questions/28127513/...
Konst54

2

对于Python 3用户:

将编码从“ ascii”更改为“ latin1”起作用。

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

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

2

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

我先做了

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

locale.getpreferredencoding(False)open()不提供编码时调用的函数。输出应该是'UTF-8',但是在这种情况下,它是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=

因此,我使用的是默认的Ubuntu语言环境,这会导致Python将文件打开为ASCII而不是UTF-8。我必须将语言环境设置en_US.UTF-8

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

如果无法在整个系统范围内更改语言环境,则可以像下面这样调用所有Python代码:

PYTHONIOENCODING="UTF-8" python3 ./path/to/your/script.py

或做

export PYTHONIOENCODING="UTF-8"

在运行它的shell中设置它。



0

或者,如果您使用Python处理文本(如果它是Unicode文本),请记下它是Unicode。

设置text=u'unicode text'只是text='unicode text'

在我看来,这是可行的。


0

由于纬度和经度而使用UTF 16编码打开。

with open(csv_name_here, 'r', encoding="utf-16") as f:

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.