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.