UnicodeDecodeError: 'ascii'编解码器无法解码第13个位置的0xe2字节:该序数不在128的范围内。

161
我将使用NLTK在文本文件中执行kmeans聚类,其中每行被视为一个文档。例如,我的文本文件如下:
belong finger death punch <br>
hasty <br>
mike hasty walls jericho <br>
jägermeister rules <br>
rules bands follow performing jägermeister stage <br>
approach 

现在我正在尝试运行的演示代码是:

import sys

import numpy
from nltk.cluster import KMeansClusterer, GAAClusterer, euclidean_distance
import nltk.corpus
from nltk import decorators
import nltk.stem

stemmer_func = nltk.stem.EnglishStemmer().stem
stopwords = set(nltk.corpus.stopwords.words('english'))

@decorators.memoize
def normalize_word(word):
    return stemmer_func(word.lower())

def get_words(titles):
    words = set()
    for title in job_titles:
        for word in title.split():
            words.add(normalize_word(word))
    return list(words)

@decorators.memoize
def vectorspaced(title):
    title_components = [normalize_word(word) for word in title.split()]
    return numpy.array([
        word in title_components and not word in stopwords
        for word in words], numpy.short)

if __name__ == '__main__':

    filename = 'example.txt'
    if len(sys.argv) == 2:
        filename = sys.argv[1]

    with open(filename) as title_file:

        job_titles = [line.strip() for line in title_file.readlines()]

        words = get_words(job_titles)

        # cluster = KMeansClusterer(5, euclidean_distance)
        cluster = GAAClusterer(5)
        cluster.cluster([vectorspaced(title) for title in job_titles if title])

        # NOTE: This is inefficient, cluster.classify should really just be
        # called when you are classifying previously unseen examples!
        classified_examples = [
                cluster.classify(vectorspaced(title)) for title in job_titles
            ]

        for cluster_id, title in sorted(zip(classified_examples, job_titles)):
            print cluster_id, title

(这里也可以找到

我收到的错误信息是:

Traceback (most recent call last):
File "cluster_example.py", line 40, in
words = get_words(job_titles)
File "cluster_example.py", line 20, in get_words
words.add(normalize_word(word))
File "", line 1, in
File "/usr/local/lib/python2.7/dist-packages/nltk/decorators.py", line 183, in memoize
result = func(*args)
File "cluster_example.py", line 14, in normalize_word
return stemmer_func(word.lower())
File "/usr/local/lib/python2.7/dist-packages/nltk/stem/snowball.py", line 694, in stem
word = (word.replace(u"\u2019", u"\x27")
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 13: ordinal not in range(128)

这里发生了什么?
11个回答

144

该文件被读取为一堆str, 但应该是unicode. Python尝试隐式转换,但失败了。更改:

job_titles = [line.strip() for line in title_file.readlines()]

要将 str 显式解码为 unicode(这里假设为UTF-8):


job_titles = [line.decode('utf-8').strip() for line in title_file.readlines()]

你也可以通过导入codecs模块并使用codecs.open而不是内置的open来解决这个问题。


2
运行这一行代码.decode('utf-8').strip().lower().split() 也给我同样的错误。我已经添加了 .decode('utf-8')。 - Aman Mathur
1
@kathirraja:你能提供一个参考吗?据我所知,即使在Python 3中,decode方法仍然是将字节字符串解码为Unicode字符串的首选方式。(尽管,我的答案中的类型对于Python 3来说不正确--对于Python 3,我们正在尝试从bytes转换为str而不是从str转换为unicode。) - icktoofay

70

这对我来说很好用。

f = open(file_path, 'r+', encoding="utf-8")

你可以添加第三个参数 encoding 以确保编码类型为 'utf-8'

注意:这种方法在Python3中可行,但我没有尝试过Python2.7。


它在Python 2.7.10中无法工作: TypeError: 'encoding'是此函数的无效关键字参数 - Borhan Kazimipour
2
它在Python 2.7.10中无法工作: TypeError: 'encoding' is an invalid keyword argument for this function这个可以正常工作:with io.open(file_path, 'r', encoding="utf-8") as f: for line in f: do_something(line)``` - Borhan Kazimipour
2
在Python3.6中完美运行。非常感谢! - SRC

48

对我来说,终端编码出现了问题。在.bashrc文件中添加UTF-8解决了这个问题:

export LC_CTYPE=en_US.UTF-8

别忘了之后重新加载.bashrc文件:

source ~/.bashrc

7
我在Ubuntu 18.04.3和Python 3.6.8上不得不使用export LC_ALL=C.UTF-8。否则,这个解决方案很好地解决了我的问题,谢谢。 - jbaranski
1
对我来说,使用 set -x LANG en_US.UTF-8(fish)在 macOS 10.15.7 和 Python 3.6.7 上解决了这个问题。 - andresp
在我的情况下,我使用了“export LC_ALL =”来恢复之前的修复,以便xclock可以呈现字体设置为“export LC_ALL = C”。然后,“LC_TYPE”回到了“en_US.UTF-8”。当然,我们也可以从文件中删除UTF-8字符并将其保留为ASCII。 - brookbot

36

你也可以尝试这个:

import sys
reload(sys)
sys.setdefaultencoding('utf8')

3
这意味着什么?听起来似乎是全球性的而不仅适用于这个文件。 - simeg
4
请注意,在Python 3中,以上内容已被弃用。 - gented

26

当我尝试在Docker容器中安装Python包时,出现了这个错误。对我来说,问题在于docker镜像没有配置locale。将以下代码添加到Dockerfile中,问题就得到了解决。

# Avoid ascii errors when reading files in Python
RUN apt-get install -y locales && locale-gen en_US.UTF-8
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' LC_ALL='en_US.UTF-8'

1
我不得不使用这个:https://github.com/docker-library/python/issues/13 - mayrop

17

在使用Python3.6的Ubuntu 18.04上,我解决了这个问题:

with open(filename, encoding="utf-8") as lines:

如果您正在命令行中运行该工具:

export LC_ALL=C.UTF-8

请注意,如果您使用的是Python2.7,则需要进行不同的处理。首先,您需要设置默认编码:

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

然后,要加载文件,您必须使用io.open设置编码:

import io
with io.open(filename, 'r', encoding='utf-8') as lines:

你仍然需要导出环境变量

export LC_ALL=C.UTF-8

5
使用以下命令来查找所有与Unicode错误相关的问题:
grep -r -P '[^\x00-\x7f]' /etc/apache2 /etc/letsencrypt /etc/nginx

我在这里找到了翻译的内容:

/etc/letsencrypt/options-ssl-nginx.conf:        # The following CSP directives don't use default-src as 

使用shed工具,我找到了问题所在的序列。原来是编辑器的错误。

00008099:     C2  194 302 11000010
00008100:     A0  160 240 10100000
00008101:  d  64  100 144 01100100
00008102:  e  65  101 145 01100101
00008103:  f  66  102 146 01100110
00008104:  a  61  097 141 01100001
00008105:  u  75  117 165 01110101
00008106:  l  6C  108 154 01101100
00008107:  t  74  116 164 01110100
00008108:  -  2D  045 055 00101101
00008109:  s  73  115 163 01110011
00008110:  r  72  114 162 01110010
00008111:  c  63  099 143 01100011
00008112:     C2  194 302 11000010
00008113:     A0  160 240 10100000

3

使用 open(fn, 'rb').read().decode('utf-8') 代替 open(fn).read()


1

在使用job_titles字符串之前,您可以尝试这个:

source = unicode(job_titles, 'utf-8')

Python2还是Python3? - Vishal Kumar Sahu

0
对于Python 3来说,默认的编码方式是"utf-8"。在基础文档中建议按照以下步骤进行操作:https://docs.python.org/2/library/csv.html#csv-examples,以防出现任何问题。
  1. 创建一个函数

    def utf_8_encoder(unicode_csv_data):
        for line in unicode_csv_data:
            yield line.encode('utf-8')
    
  2. 然后在读取器中使用该函数,例如:

    csv_reader = csv.reader(utf_8_encoder(unicode_csv_data))
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接