UnicodeDecodeError: il codec 'ascii' non può decodificare il byte 0xe2 in posizione 13: ordinale non compreso nell'intervallo (128)


129

Sto usando NLTK per eseguire il raggruppamento di kmean sul mio file di testo in cui ogni riga è considerata come un documento. Ad esempio, il mio file di testo è simile al seguente:

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 

Ora il codice demo che sto cercando di eseguire è questo:

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

(che puoi trovare anche qui )

L'errore che ricevo è questo:

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)

Cosa sta succedendo qui?

Risposte:


133

Il file viene letto come un gruppo di strs, ma dovrebbe essere unicodes. Python tenta di convertire implicitamente, ma non riesce. Modificare:

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

per decodificare esplicitamente la strs in unicode(qui assumendo UTF-8):

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

Potrebbe anche essere risolto importando il codecsmodulo e usando codecs.openanziché il built-in open.


2
eseguire questo line.decode ('utf-8'). strip (). lower (). split () mi dà lo stesso errore. Ho aggiunto il .deocode ('utf-8')
Aman Mathur il

@kathirraja: puoi fornire un riferimento per questo? Per quanto ne so, anche in Python 3, il decodemetodo rimane il modo preferito per decodificare una stringa di byte in una stringa Unicode. (Tuttavia, i tipi nella mia risposta non sono giusti per Python 3 - per Python 3, stiamo provando a convertire da bytesin strpiuttosto che da stra unicode.)
icktoofay

52

Questo funziona bene per me.

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

È possibile aggiungere un terzo parametro codifica per assicurarti che il tipo di codifica sia 'utf-8'

Nota: questo metodo funziona bene in Python3, non l'ho provato in Python2.7.


Non funziona in Python 2.7.10:TypeError: 'encoding' is an invalid keyword argument for this function
Borhan Kazimipour il

2
Non funziona in Python 2.7.10: TypeError: 'encoding' is an invalid keyword argument for this function Funziona bene:import io with io.open(file_path, 'r', encoding="utf-8") as f: for line in f: do_something(line)
Borhan Kazimipour,

2
Ha funzionato come un incantesimo in python3.6 Grazie mille!
SRC

32

Per me c'è stato un problema con la codifica del terminale. L'aggiunta di UTF-8 a .bashrc ha risolto il problema:

export LC_CTYPE=en_US.UTF-8

Non dimenticare di ricaricare .bashrc in seguito:

source ~/.bashrc

3
Ho dovuto usare export LC_ALL=C.UTF-8su Ubuntu 18.04.3 e Python 3.6.8. Altrimenti questo ha risolto il mio problema, grazie.
jbaranski,

31

Puoi provare anche questo:

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

3
Che cosa implica ciò? Sembra che sia qualcosa di globale e non applicabile solo per questo file.
simeg

2
Si noti che quanto sopra è deprecato in Python 3.
modificato il

12

Quando su Ubuntu 18.04 usando Python3.6 ho risolto il problema facendo entrambe le cose:

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

e se si esegue lo strumento come riga di comando:

export LC_ALL=C.UTF-8

Nota che se sei in Python2.7 devi farlo per gestirlo diversamente. Per prima cosa devi impostare la codifica predefinita:

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

e quindi per caricare il file è necessario utilizzare io.openper impostare la codifica:

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

Hai ancora bisogno di esportare l'ENV

export LC_ALL=C.UTF-8

6

Ho riscontrato questo errore durante il tentativo di installare un pacchetto Python in un contenitore Docker. Per me, il problema era che l'immagine della finestra mobile non aveva una localeconfigurazione. L'aggiunta del seguente codice al Dockerfile ha risolto il problema per me.

# 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'


3

Per trovare QUALSIASI e TUTTO l'errore unicode correlato ... Utilizzando il seguente comando:

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

Ho trovato il mio

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

Usando shed, ho trovato la sequenza offensiva. Si è rivelato essere un errore dell'editor.

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

Puoi provare questo prima di usare job_titlesstring:

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

0

Per python 3, la codifica predefinita sarebbe "utf-8". I seguenti passaggi sono suggeriti nella documentazione di base: https://docs.python.org/2/library/csv.html#csv-examples in caso di problemi

  1. Crea una funzione

    def utf_8_encoder(unicode_csv_data):
        for line in unicode_csv_data:
            yield line.encode('utf-8')
  2. Quindi utilizzare la funzione all'interno del lettore, ad es

    csv_reader = csv.reader(utf_8_encoder(unicode_csv_data))

0

python3x o superiore

  1. carica il file nel flusso di byte:

    body = '' per le linee aperte ('website / index.html', 'rb'): decodedLine = lines.decode ('utf-8') body = body + decodedLine.strip () return body

  2. usa l'impostazione globale:

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


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.