Errore di codifica Unicode Python


104

Sto leggendo e analizzando un file XML di Amazon e mentre il file XML mostra un ', quando provo a stamparlo ottengo il seguente errore:

'ascii' codec can't encode character u'\u2019' in position 16: ordinal not in range(128) 

Da quello che ho letto online finora, l'errore deriva dal fatto che il file XML è in UTF-8, ma Python vuole trattarlo come un carattere codificato ASCII. C'è un modo semplice per eliminare l'errore e fare in modo che il mio programma stampi l'XML mentre legge?


Stavo venendo a SO per pubblicare questa domanda. C'è un modo semplice per disinfettare una stringa unicode()?
Nick Heiner

Si prega di controllare anche questa risposta a una domanda correlata: "Python UnicodeDecodeError - Am I misunderstanding encode?"
tzot

Risposte:


193

Probabilmente, il tuo problema è che l'hai analizzato bene, e ora stai cercando di stampare il contenuto dell'XML e non puoi perché ci sono alcuni caratteri Unicode stranieri. Prova prima a codificare la tua stringa Unicode come ascii:

unicodeData.encode('ascii', 'ignore')

la parte "ignora" gli dirà di saltare semplicemente quei caratteri. Dai documenti di Python:

>>> u = unichr(40960) + u'abcd' + unichr(1972)
>>> u.encode('utf-8')
'\xea\x80\x80abcd\xde\xb4'
>>> u.encode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
UnicodeEncodeError: 'ascii' codec can't encode character '\ua000' in position 0: ordinal not in range(128)
>>> u.encode('ascii', 'ignore')
'abcd'
>>> u.encode('ascii', 'replace')
'?abcd?'
>>> u.encode('ascii', 'xmlcharrefreplace')
'&#40960;abcd&#1972;'

Potresti leggere questo articolo: http://www.joelonsoftware.com/articles/Unicode.html , che ho trovato molto utile come tutorial di base su cosa sta succedendo. Dopo la lettura, smetterai di sentirti come se stessi solo indovinando quali comandi usare (o almeno quello è successo a me).


1
Sto cercando di rendere sicura la seguente stringa: 'foo “bar bar” df' (notare le virgolette ricce), ma quanto sopra non riesce ancora per me.
Nick Heiner

@Rosarch: come fallisce? stesso errore? E quale regola di gestione degli errori hai usato?
Scott Stafford

@ Rosarch, probabilmente il tuo problema è precedente. Prova questo codice: # - - coding: latin-1 - - u = u 'foo "bar bar" df' print u.encode ('ascii', 'ignore') Per te, probabilmente stava convertendo la tua stringa in unicode data la codifica specificata per lo script Python che ha generato l'errore.
Scott Stafford

Sono andato avanti e ho trasformato il mio problema in una sua domanda: stackoverflow.com/questions/3224427/…
Nick Heiner

1
.encode('ascii', 'ignore')perde dati inutilmente anche se l'ambiente di OP può supportare caratteri non ASCII (la maggior parte dei casi)
jfs

16

Una soluzione migliore:

if type(value) == str:
    # Ignore errors even if the string is not proper UTF-8 or has
    # broken marker bytes.
    # Python built-in function unicode() can do this.
    value = unicode(value, "utf-8", errors="ignore")
else:
    # Assume the value object has proper __unicode__() method
    value = unicode(value)

Se vuoi saperne di più sul perché:

http://docs.plone.org/manage/troubleshooting/unicode.html#id1


3
Non aiuta con il problema di OP: "impossibile codificare il carattere u '\ u2019'" . u'\u2019è già Unicode.
jfs

6

Non codificare in modo rigido la codifica dei caratteri del tuo ambiente all'interno dello script; stampa invece direttamente il testo Unicode:

assert isinstance(text, unicode) # or str on Python 3
print(text)

Se l'output viene reindirizzato a un file (o una pipe); potresti usare PYTHONIOENCODINGenvvar, per specificare la codifica dei caratteri:

$ PYTHONIOENCODING=utf-8 python your_script.py >output.utf8

In caso contrario, python your_script.pydovrebbe funzionare come è - le tue impostazioni locali vengono utilizzate per codificare il testo (al momento del check POSIX: LC_ALL, LC_CTYPE, LANGenvvars - insiemeLANG ad un locale UTF-8, se necessario).

Per stampare Unicode su Windows, vedere questa risposta che mostra come stampare Unicode sulla console di Windows, su un file o utilizzando IDLE .


1

Post eccellente: http://www.carlosble.com/2010/12/understanding-python-and-unicode/

# -*- coding: utf-8 -*-

def __if_number_get_string(number):
    converted_str = number
    if isinstance(number, int) or \
            isinstance(number, float):
        converted_str = str(number)
    return converted_str


def get_unicode(strOrUnicode, encoding='utf-8'):
    strOrUnicode = __if_number_get_string(strOrUnicode)
    if isinstance(strOrUnicode, unicode):
        return strOrUnicode
    return unicode(strOrUnicode, encoding, errors='ignore')


def get_string(strOrUnicode, encoding='utf-8'):
    strOrUnicode = __if_number_get_string(strOrUnicode)
    if isinstance(strOrUnicode, unicode):
        return strOrUnicode.encode(encoding)
    return strOrUnicode

0

Puoi usare qualcosa del modulo

s.decode('utf-8')

che convertirà una stringa codificata UTF-8 in una stringa Python Unicode. Ma la procedura esatta da utilizzare dipende esattamente da come carichi e analizzi il file XML, ad esempio se non accedi mai direttamente alla stringa XML, potresti dover utilizzare un oggetto decodificatore dal codecsmodulo .


È già codificato in UTF-8 L'errore è specificamente: myStrings = deque ([il testo di u'Dorf e Svoboda si basa su str ... e le sottodiscipline di Computer Engineering. ']) La stringa è in UTF-8 come puoi vedere, ma si arrabbia per l'interno "\ u2019"
Alex B

Oh, ok, pensavo avessi un problema diverso.
David Z

7
@Alex B: No, la stringa è Unicode, non Utf-8. Per codificarlo come Utf-8 usa'...'.encode('utf-8')
sth

0

Ho scritto quanto segue per correggere le fastidiose citazioni non ASCII e forzare la conversione in qualcosa di utilizzabile.

unicodeToAsciiMap = {u'\u2019':"'", u'\u2018':"`", }

def unicodeToAscii(inStr):
    try:
        return str(inStr)
    except:
        pass
    outStr = ""
    for i in inStr:
        try:
            outStr = outStr + str(i)
        except:
            if unicodeToAsciiMap.has_key(i):
                outStr = outStr + unicodeToAsciiMap[i]
            else:
                try:
                    print "unicodeToAscii: add to map:", i, repr(i), "(encoded as _)"
                except:
                    print "unicodeToAscii: unknown code (encoded as _)", repr(i)
                outStr = outStr + "_"
    return outStr

0

Se hai bisogno di stampare una rappresentazione approssimativa della stringa sullo schermo, invece di ignorare quei caratteri non stampabili, prova il unidecodepacchetto qui:

https://pypi.python.org/pypi/Unidecode

La spiegazione si trova qui:

https://www.tablix.org/~avian/blog/archives/2009/01/unicode_transliteration_in_python/

È meglio che usare u.encode('ascii', 'ignore')per una determinata stringa ue può salvarti da inutili mal di testa se la precisione dei caratteri non è ciò che stai cercando, ma vuoi comunque avere la leggibilità umana.

Wirawan


-1

Prova ad aggiungere la seguente riga all'inizio del tuo script Python.

# _*_ coding:utf-8 _*_

-1

Python 3.5, 2018

Se non sai quale sia la codifica ma il parser Unicode sta avendo problemi, puoi aprire il file Notepad++e selezionare nella barra in alto Encoding->Convert to ANSI. Quindi puoi scrivere il tuo pitone in questo modo

with open('filepath', 'r', encoding='ANSI') as file:
    for word in file.read().split():
        print(word)
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.