UnicodeDecodeError: кодек ascii не может декодировать байт 0xe2 в позиции 13: порядковый номер не в диапазоне (128)

129

Я использую 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)

Что здесь происходит?

user2602812
источник

Ответы:

133

Файл читается как группа strs, но это должно быть unicodes. Python пытается неявно преобразовать, но терпит неудачу. Изменить:

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

чтобы явно декодировать strs в unicode(здесь предполагается UTF-8):

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

Она также может быть решена за счет импорта в codecsмодуль и использования , codecs.openа не встроенный open.

icktoofay
источник
2
запуск этой строки .decode ('utf-8'). strip (). lower (). split () также дает мне ту же ошибку. Я добавил .deocode ('utf-8')
Аман Матур
@kathirraja: Можете ли вы дать ссылку на это? Насколько мне известно, даже в Python 3 этот decodeметод остается предпочтительным способом декодирования байтовой строки в строку Unicode. (Хотя типы в моем ответе не подходят для Python 3 - для Python 3 мы пытаемся преобразовать из bytesв, strа не из strв unicode.)
icktoofay
52

У меня это отлично работает.

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

Вы можете добавить третий параметр кодировки, чтобы убедиться, что тип кодировки - utf-8.

Примечание: этот метод отлично работает в Python3, я не пробовал его в Python2.7.

uestcfei
источник
Это не работает в Python 2.7.10:TypeError: 'encoding' is an invalid keyword argument for this function
Borhan Kazimipour
2
Это не работает в Python 2.7.10: TypeError: 'encoding' is an invalid keyword argument for this function Это отлично работает:import io with io.open(file_path, 'r', encoding="utf-8") as f: for line in f: do_something(line)
Borhan Kazimipour
2
Работал как шарм в python3.6 Большое спасибо!
SRC
32

У меня возникла проблема с кодировкой терминала. Добавление UTF-8 в .bashrc решило проблему:

export LC_CTYPE=en_US.UTF-8

Не забудьте после этого перезагрузить .bashrc:

source ~/.bashrc
Георгий Караджов
источник
3
Мне пришлось использовать export LC_ALL=C.UTF-8Ubuntu 18.04.3 и Python 3.6.8. В противном случае это решило мою проблему, спасибо.
jbaranski
31

Вы также можете попробовать это:

import sys
reload(sys)
sys.setdefaultencoding('utf8')
Шива С
источник
3
Какие из этого последствия? Похоже, это что-то глобальное и применимое не только для этого файла.
simeg
2
Обратите внимание, что указанное выше устарело в Python 3.
создано
12

В Ubuntu 18.04 с использованием Python3.6 я решил проблему, выполнив оба:

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:

Вам все еще нужно экспортировать env

export LC_ALL=C.UTF-8
loretoparisi
источник
6

Я получил эту ошибку при попытке установить пакет 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'
Джейкоб Стерн
источник
Мне пришлось использовать это: github.com/docker-library/python/issues/13
mayrop
4

Чтобы найти ЛЮБУЮ и ВСЕ ошибки, связанные с 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
Джон Грин
источник
1

Вы можете попробовать это перед использованием job_titlesстроки:

source = unicode(job_titles, 'utf-8')
Амина Нураини
источник
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))
iamigham
источник
0

python3x или выше

  1. загрузить файл в байтовый поток:

    body = '' для строк в open ('website / index.html', 'rb'): decodedLine = lines.decode ('utf-8') body = body + decodedLine.strip () return body

  2. использовать глобальную настройку:

    import io import sys sys.stdout = io.TextIOWrapper (sys.stdout.buffer, encoding = 'utf-8')

io большой
источник
0

Используйте open(fn, 'rb').read().decode('utf-8')вместоopen(fn).read()

Ганеш Харад
источник