UnicodeDecodeError: el códec 'ascii' no puede decodificar el byte 0xe2 en la posición 13: el ordinal no está en el rango (128)

129

Estoy usando NLTK para realizar la agrupación de kmeans en mi archivo de texto en el que cada línea se considera como un documento. Entonces, por ejemplo, mi archivo de texto es algo como esto:

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 

Ahora el código de demostración que intento ejecutar es este:

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

(que también se puede encontrar aquí )

El error que recibo es este:

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)

¿Que está sucediendo aquí?

user2602812
fuente

Respuestas:

133

El archivo se lee como un montón de strs, pero debería ser unicodes. Python intenta convertir implícitamente, pero falla. Cambio:

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

para decodificar explícitamente el strs a unicode(aquí suponiendo UTF-8):

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

También podría resolverse importando el codecsmódulo y utilizando en codecs.openlugar del incorporado open.

icktoofay
fuente
2
ejecutar este line.decode ('utf-8'). strip (). lower (). split () también me da el mismo error. He agregado el .deocode ('utf-8')
Aman Mathur
@kathirraja: ¿Puedes proporcionar una referencia para eso? Hasta donde sé, incluso en Python 3, el decodemétodo sigue siendo la forma preferida de decodificar una cadena de bytes en una cadena Unicode. (Sin embargo, los tipos en mi respuesta no son los adecuados para Python 3 - para Python 3, estamos tratando de convertir de bytesa stren lugar de stra unicode.)
icktoofay
52

Esto funciona bien para mi.

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

Puede agregar un tercer parámetro de codificación para asegurarse de que el tipo de codificación sea 'utf-8'

Nota: este método funciona bien en Python3, no lo probé en Python2.7.

uestcfei
fuente
No funciona en Python 2.7.10:TypeError: 'encoding' is an invalid keyword argument for this function
Borhan Kazimipour
2
No funciona en Python 2.7.10: TypeError: 'encoding' is an invalid keyword argument for this function Esto funciona bien:import io with io.open(file_path, 'r', encoding="utf-8") as f: for line in f: do_something(line)
Borhan Kazimipour
2
Funcionó como un encanto en python3.6 ¡Muchas gracias!
SRC
32

Para mí hubo un problema con la codificación del terminal. Agregar UTF-8 a .bashrc resolvió el problema:

export LC_CTYPE=en_US.UTF-8

No olvides volver a cargar .bashrc después:

source ~/.bashrc
Georgi Karadzhov
fuente
3
Tuve que usar export LC_ALL=C.UTF-8en Ubuntu 18.04.3 y Python 3.6.8. De lo contrario, esto resolvió mi problema, gracias.
jbaranski
31

Puedes probar esto también:

import sys
reload(sys)
sys.setdefaultencoding('utf8')
Siva S
fuente
3
¿Cuáles son las implicaciones de esto? Parece que es algo global y no solo aplicable para este archivo.
simeg
2
Tenga en cuenta que lo anterior está en desuso en Python 3.
Gented
12

Cuando en Ubuntu 18.04 usando Python3.6 , he resuelto el problema haciendo ambas cosas:

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

y si está ejecutando la herramienta como línea de comando:

export LC_ALL=C.UTF-8

Tenga en cuenta que si está en Python2.7 tiene que hacer para manejar esto de manera diferente. Primero debe establecer la codificación predeterminada:

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

y luego para cargar el archivo que debe usar io.openpara configurar la codificación:

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

Aún necesitas exportar el env

export LC_ALL=C.UTF-8
loretoparisi
fuente
6

Recibí este error al intentar instalar un paquete de Python en un contenedor Docker. Para mí, el problema era que la imagen de la ventana acoplable no estaba localeconfigurada. Agregar el siguiente código al Dockerfile resolvió el problema para mí.

# 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'
Jacob Stern
fuente
Tuve que usar esto: github.com/docker-library/python/issues/13
mayrop
3

Para encontrar CUALQUIER y TODOS los errores unicode relacionados ... Usando el siguiente comando:

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

Encontré el mío en

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

Usando shed, encontré la secuencia ofensiva. Resultó ser un error del 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
John Greene
fuente
1

Puedes probar esto antes de usar job_titlesstring:

source = unicode(job_titles, 'utf-8')
Aminah Nuraini
fuente
0

Para python 3, la codificación predeterminada sería "utf-8". Los siguientes pasos se sugieren en la documentación base: https://docs.python.org/2/library/csv.html#csv-examples en caso de cualquier problema

  1. Crear una función

    def utf_8_encoder(unicode_csv_data):
        for line in unicode_csv_data:
            yield line.encode('utf-8')
  2. Luego use la función dentro del lector, por ejemplo

    csv_reader = csv.reader(utf_8_encoder(unicode_csv_data))
iamigham
fuente
0

python3x o superior

  1. cargar archivo en flujo de bytes:

    body = '' para líneas en abierto ('sitio web / index.html', 'rb'): decodedLine = lines.decode ('utf-8') body = body + decodedLine.strip () return body

  2. usar configuración global:

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

io grande
fuente
0

Usar en open(fn, 'rb').read().decode('utf-8')lugar de soloopen(fn).read()

Ganesh Kharad
fuente