UnicodeEncodeError: ‘ascii’ codec riesco a codificare il carattere u’\xa0′ in posizione 20: ordinale non in range(128)

Sto avendo problemi a trattare con i caratteri unicode dal testo prelevato da diverse pagine web (su diversi siti). Sto usando Coherence.

Il problema è che l’errore non è sempre riproducibile; funziona a volte con alcune pagine, a volte, è barfs con il lancio di un UnicodeEncodeError. Ho provato quasi tutto quello che posso pensare, e ancora non ho trovato qualcosa che funziona in modo coerente, senza buttare un qualche tipo di Unicode di errore correlati.

Una delle sezioni di codice che sta causando i problemi è mostrato di seguito:

agent_telno = agent.find('div', 'agent_contact_number')
agent_telno = '' if agent_telno is None else agent_telno.contents[0]
p.agent_info = str(agent_contact + ' ' + agent_telno).strip()

Qui è una traccia dello stack prodotto su ALCUNE stringhe quando il frammento di sopra viene eseguito:

Traceback (most recent call last):
  File "foobar.py", line 792, in <module>
    p.agent_info = str(agent_contact + ' ' + agent_telno).strip()
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 20: ordinal not in range(128)

Ho il sospetto che questo è perché alcune pagine (o, più specificamente, le pagine di alcuni siti) possono essere codificati, mentre altri possono essere in chiaro. Tutti i siti sono basati nel regno UNITO e fornire dati significava per il regno UNITO, con il consumo, in modo che non ci siano problemi relativi alla interiorizzazione o trattare con il testo scritto in altro che in inglese.

Qualcuno ha qualche idea su come risolvere questo in modo che io possa sempre risolvere questo problema?

Se stai ricevendo questi errori come un utente piuttosto che come sviluppatore, serverfault.com/questions/54591/… e askubuntu.com/questions/599808/…
Vorrei aggiungere questo punto non usare onlinegdb.com/online_python_interpreter per questa roba. È stato utilizza interprete a prova di roba e non è configurato correttamente per Unicode! Era sempre la stampa in un formato ‘B’\nnn”… quando tutto quello che volevo era un guillemet! Provato su una macchina virtuale e ha funzionato immediatamente, come previsto, utilizzando chr()

OriginaleL’autore Homunculus Reticulli | 2012-03-30

19 Replies
  1. 1125

    È necessario leggere il Python Unicode HOWTO. Questo errore è il primo esempio.

    Fondamentalmente, smettere di usare str per la conversione da unicode codifica di testo /byte.

    Invece, usare correttamente .encode() per codificare la stringa:

    p.agent_info = u' '.join((agent_contact, agent_telno)).encode('utf-8').strip()

    o di un lavoro interamente in unicode.

    d’accordo! una buona regola che mi è stata insegnata è quello di utilizzare il “unicode sandwich” idea. Il tuo script accetta byte dal mondo esterno, ma tutto il trattamento dovrebbe essere fatto in unicode. Solo quando si è pronti per l’output dei dati dovrebbe essere mushed di nuovo in byte!
    Nel caso qualcun altro abbia confuso da questo, ho trovato una cosa strana: il mio terminale utilizza la codifica utf-8, e quando ho print mio utf-8 corde funziona bene. Tuttavia, quando ho di tubo miei programmi di output in un file, genera una UnicodeEncodeError. Infatti, quando l’uscita viene reindirizzato (a un file o a un tubo), trovo che sys.stdout.encoding è None! Virare su .encode('utf-8') risolve il problema.
    utilizzare PYTHONIOENCODING=utf-8 invece cioè, stampa, stringhe Unicode e lasciare che l’ambiente per impostare il previsto codifica.
    Questo è un male e confuso consigli. Il motivo per cui la gente usa str è perché l’oggetto NON È già una stringa, quindi non c’è .encode() metodo da chiamare.
    No, non è così. Era solo copiato dal codice originale, come il join e i nomi delle variabili. È qualcosa di specifico per il suo caso d’uso.

    OriginaleL’autore agf

  2. 385

    Questo è un classico unicode python dolore! Si consideri il seguente:

    a = u'bats\u00E0'
    print a
     => batsà

    Tutto bene finora, ma se chiamiamo str(a), vediamo cosa succede:

    str(a)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)

    Oh dip, che non è intenzione di fare, nessuno, bene! Per correggere l’errore, la codifica del byte in modo esplicito .codificare e dire a python che il codec da utilizzare:

    a.encode('utf-8')
     => 'bats\xc3\xa0'
    print a.encode('utf-8')
     => batsà

    Voil\u00E0!

    Il problema è che quando si chiama str(), python utilizza la codifica dei caratteri predefinita per provare a codificare i byte che hai dato, che nel tuo caso a volte sono rappresentazioni di caratteri unicode. Per risolvere il problema, si deve dire a python come trattare con la stringa di dare utilizzando .encode(‘whatever_unicode’). La maggior parte del tempo, si dovrebbe andare bene usando utf-8.

    Un’ottima esposizione su questo argomento, vedere Ned Batchelder del PyCon parlare qui: http://nedbatchelder.com/text/unipain.html

    Nota personale: Quando si tenta di tipo “.encode” per non rischiare di tipo “.unicode” poi si chiedono perché non sempre c’è.
    Un buon consiglio. Ma cosa fare invece quando si utilizza str(x) per la stampa di oggetti che possono o non possono essere stringhe? str(x) se x è un numero, data e ora, boolean, o una stringa normale. Improvvisamente se la sua unicode smette di funzionare. C’è un modo per ottenere lo stesso comportamento o abbiamo bisogno di aggiungere un controllo per verificare se l’oggetto è la stringa da utilizzare .codificare e str (), altrimenti?
    Stessa domanda si potrebbe essere chiesto con None valore.

    OriginaleL’autore Andbdrew

  3. 176

    Ho trovato elegante aggirare per me di rimuovere i simboli e continuare a mantenere la stringa di stringa nel seguente modo:

    yourstring = yourstring.encode('ascii', 'ignore').decode('ascii')

    È importante notare che utilizzando l’opzione ignora è pericoloso perché in silenzio gocce unicode(internazionalizzazione) supporto dal codice che utilizza, come si può vedere qui (la conversione unicode):

    >>> u'City: Malmö'.encode('ascii', 'ignore').decode('ascii')
    'City: Malm'
    Hai fatto la mia giornata! Per utf-8, è sufficiente fare: yourstring = yourstring.encode('utf-8', 'ignore').decode('utf-8')
    per me questo ha fatto il lavoro, ma il mio caso era diverso, ero risparmio i nomi di file e di aver “/” il nome e il percorso non esisteva quindi devo utilizzare .replace(“/”,””) e quindi salvato miei script. ignorando l’ascii funziona anche per ‘utf-8’ caso.
    per la concatenazione di percorsi di file utilizzare correttamente os.path.join(), è una buona abitudine, quando si inizia a fare cross-piattaforma di programmazione. 🙂

    OriginaleL’autore Max Korolevsky

  4. 121

    beh, ho provato di tutto ma non di aiuto, dopo googling intorno ho capito che la segue e che ha aiutato.
    python 2.7 è in uso.

    # encoding=utf8
    import sys
    reload(sys)
    sys.setdefaultencoding('utf8')
    Non fare questo. stackoverflow.com/questions/3828723/…, anche se quando si hanno risposte di questo genere stackoverflow.com/a/31137935/2141635 vicino alla parte superiore dei risultati quando si cerca l’errore che può vedere il motivo per cui può sembrare una buona idea.
    Ho provato quasi tutti i suggerimenti in questo argomento e davvero nessuno ha lavorato per me. Infine ho provato anche questo. Ed è davvero L’UNICA cosa che ha funzionato semplice e buona. Se qualcuno dice “non fare questo, e poi venire con una Soluzione semplice. Altrimenti usare questo. Perché è una buona copia di lavoro, e passato soluzione.
    Come potrebbe essere fatto in python3 ? Sarebbe felice di sapere.
    Dopo tanta frustrazione che questo ha funzionato. Grazie mille.
    Vorrei solo aggiungere un if sys.version_info.major < 3:

    OriginaleL’autore Ashwin

  5. 79

    Un sottile problema che causa anche la stampa non è di avere il vostro set di variabili di ambiente sbagliato, ad esempio. qui LC_ALL impostato a “C”. In Debian scoraggiano l’impostazione: Il wiki di Debian su impostazioni Internazionali

    $ echo $LANG
    en_US.utf8
    $ echo $LC_ALL 
    C
    $ python -c "print (u'voil\u00e0')"
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)
    $ export LC_ALL='en_US.utf8'
    $ python -c "print (u'voil\u00e0')"
    voilà
    $ unset LC_ALL
    $ python -c "print (u'voil\u00e0')"
    voilà
    Ha esattamente lo stesso problema, così male non ho controllato prima creazione. Grazie mille. A proposito, è possibile sostituire i primi due comandi con env|grep -E '(LC|LANG)'.
    Solo i miei due centesimi sul errata codifica problema. Mi capita spesso di utilizzare mc in “subshell mode” (Ctrl-O) e ho anche dimenticato che mi e ‘ aggiunto il seguente alias bash: alias mc="LANG=en_EN.UTF-8 mc". Così, quando ho provato a eseguire mal scritta script che si basano su ru_RU.UTF-8 internamente, muoiono e basta. Provato un sacco di cose da questo thread prima che ho scoperto il vero problema. 🙂

    OriginaleL’autore maxpolk

  6. 26

    In realtà ho scoperto che, nella maggior parte dei casi, solo togliendo quei personaggi è molto più semplice:

    s = mystring.decode('ascii', 'ignore')
    “Perfettamente” non è di solito quello che si esegue. Si butta via le cose di cui si dovrebbe capire come affrontare in modo corretto.
    solo togliendo il “chi” (non in inglese) caratteri non è la soluzione, dato che python deve supportare tutte le lingue, non credi?
    Downvoted. Questa non è la soluzione corretta. Imparare a lavorare con Unicode: joelonsoftware.com/articles/Unicode.html
    Guarda, il più giudizioso modo di presentare questo tipo di risposta è in questo modo: riconoscere che ascii conferisce un certo privilegio, in determinate lingue e utenti – questo è il scialuppa che possono essere sfruttati per quegli utenti che possono essere hacking di un superficiale, primo passaggio, la sceneggiatura, potenzialmente, per il lavoro preliminare prima di pieno supporto unicode è implementato.
    Se sto scrivendo uno script che ha solo bisogno di stampare un testo in inglese su stdout interno di società di applicazione, voglio solo il problema di andare via. Quello che funziona.

    OriginaleL’autore Phil LaNasa

  7. 24

    Per me, ciò che ha funzionato è stata:

    BeautifulSoup(html_text,from_encoding="utf-8")

    Spero che questo aiuta qualcuno.

    OriginaleL’autore Animesh

  8. 17

    Aggiungere una riga sotto all’inizio del tuo script ( o come seconda linea):

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

    Che la definizione di codice sorgente python codifica. Ulteriori informazioni in PEP 263.

    OriginaleL’autore Andriy Ivaneyko

  9. 14

    Il problema è che si sta tentando di stampare un carattere unicode, ma il terminale non lo supporta.

    Puoi provare a installare language-pack-en pacchetto di correzione:

    sudo apt-get install language-pack-en

    che prevede inglese aggiornamenti delle traduzioni per tutti i pacchetti supportati (tra cui Python). Installare diversi pacchetti lingua, se necessario (a seconda dei caratteri che si sta cercando di stampa).

    Su alcune distribuzioni Linux è necessario per assicurarsi che l’impostazione di inglese localizzazioni sono impostate correttamente (quindi i caratteri unicode possono essere gestiti da shell/terminale). A volte è più facile da installare, rispetto alla configurazione manuale.

    Quindi quando si scrive il codice, assicurarsi che si utilizza il diritto di codifica nel codice.

    Per esempio:

    open(foo, encoding='utf-8')

    Se avete ancora un problema, controllare la configurazione del sistema, quali:

    • Locale di file (/etc/default/locale), che dovrebbe, per esempio,

      LANG="en_US.UTF-8"
      LC_ALL="en_US.UTF-8"
    • Valore di LANG/LC_CTYPE in guscio.

    • Controllare che le impostazioni internazionali shell supporta da:

      locale -a | grep "UTF-8"

    Dimostrando il problema e la soluzione in fresco VM.

    1. Inizializzare e fornitura VM (ad esempio, utilizzando vagabondo):

      vagrant init ubuntu/trusty64; vagrant up; vagrant ssh

      Vedi: disponibile Ubuntu scatole..

    2. Stampa di caratteri unicode (come il marchio come segno ):

      $ python -c 'print(u"\u2122");'
      Traceback (most recent call last):
        File "<string>", line 1, in <module>
      UnicodeEncodeError: 'ascii' codec can't encode character u'\u2122' in position 0: ordinal not in range(128)
    3. Ora l’installazione di language-pack-en:

      $ sudo apt-get -y install language-pack-en
      The following extra packages will be installed:
        language-pack-en-base
      Generating locales...
        en_GB.UTF-8... /usr/sbin/locale-gen: done
      Generation complete.
    4. Ora il problema è risolto:

      $ python -c 'print(u"\u2122");'
      
    Che cosa ha language-pack-en ha a che fare con Python o questa domanda? Per quanto ne so, potrebbe fornire traduzioni in lingua per i messaggi, ma non ha niente a che fare con la codifica
    Su alcune distribuzioni Linux è necessario per assicurarsi che l’impostazione di inglese localizzazioni sono impostati correttamente, in particolare durante l’esecuzione di script Python sul Terminale. Ha funzionato per me a un certo punto. Vedi: codifica caratteri
    Ah, ok. Vuoi dire che se si desidera utilizzare una lingua diversa dall’inglese? Credo che l’utente potrà anche modificare /etc/locale.gen per garantire la loro localizzazione è costruito prima di utilizzarlo?
    Commentato LANG da /etc/default/locale (come /etc/locale.gen non esiste) e corse locale-gen, ma niente da fare. Io non sono sicuro di quello che language-pack-en esattamente, perché non ho trovato molta documentazione ed elencare il contenuto di esso non aiuta molto.
    è improbabile che non ci sono utf-8 su un sistema desktop già cioè, è probabile che non hai bisogno di installare nulla, basta configurare LANG/ LC_CTYPE/ LC_ALL invece (ad esempio, LANG=C.UTF-8).

    OriginaleL’autore kenorb

  10. 13

    Provare questo potrebbe risolvere,

    # encoding=utf8
    import sys
    reload(sys)
    sys.setdefaultencoding('utf8')
    Perché dovremmo reload(sys)?
    senza reload(sys), getta AttributeError: 'module' object has no attribute 'setdefaultencoding'. Ulteriori informazioni qui

    OriginaleL’autore Joseph Daudi

  11. 12

    Ecco la rielaborazione di alcuni altri cosiddetti “cop out” le risposte. Ci sono situazioni in cui semplicemente buttare via i caratteri problematici/stringhe è una buona soluzione, nonostante le proteste espresse qui.

    def safeStr(obj):
        try: return str(obj)
        except UnicodeEncodeError:
            return obj.encode('ascii', 'ignore').decode('ascii')
        except: return ""

    Collaudo:

    if __name__ == '__main__': 
        print safeStr( 1 ) 
        print safeStr( "test" ) 
        print u'98\xb0'
        print safeStr( u'98\xb0' )

    Risultati:

    1
    test
    98°
    98

    Suggerimento: si potrebbe desiderare di nome questa funzione per toAscii invece? Questa è una questione di preferenza.

    OriginaleL’autore BuvinJ

  12. 6

    Semplici funzioni di supporto trovato qui.

    def safe_unicode(obj, *args):
        """ return the unicode representation of obj """
        try:
            return unicode(obj, *args)
        except UnicodeDecodeError:
            # obj is byte string
            ascii_text = str(obj).encode('string_escape')
            return unicode(ascii_text)
    
    def safe_str(obj):
        """ return the byte string representation of obj """
        try:
            return str(obj)
        except UnicodeEncodeError:
            # obj is unicode
            return unicode(obj).encode('unicode_escape')
    Per ottenere il sfuggito bytestring (per la conversione arbitrario Unicode stringa di byte utilizzando la codifica ascii), si potrebbe utilizzare backslashreplace gestore di errore: u'\xa0'.encode('ascii', 'backslashreplace'). Anche se si dovrebbe evitare tale rappresentazione e configurare il proprio ambiente di accettare i caratteri non ascii, invece, è il 2016!
    Felice Anno Nuovo @J. F. Sebastian. Ho appena ricevuto frustrato con il Python-Unicode problema e quindi finalmente questa soluzione cui stava lavorando. Non sapevo di questo. Comunque grazie per il suggerimento.

    OriginaleL’autore Parag Tyagi -morpheus-

  13. 3

    Ho appena usato il seguente:

    import unicodedata
    message = unicodedata.normalize("NFKD", message)

    Controllare che la documentazione dice a questo proposito:

    unicodedata.normalizzare(forma, unistr) Restituire il normale modulo per
    la stringa Unicode unistr. I valori validi per il modulo sono ‘NFC’, ‘NFKC’,
    ‘NFD’, e ‘NFKD’.

    Lo standard Unicode definisce le varie forme di normalizzazione Unicode
    stringa, in base alla definizione della canonica di equivalenza e
    compatibilità di equivalenza. In Unicode, alcuni caratteri possono essere
    espressa in modo diverso. Per esempio, il carattere U+00C7 (LATINA
    LETTERA maiuscola C CON CEDIGLIA) può anche essere espressa come la sequenza
    U+0043 (LETTERA MAIUSCOLA LATINA C) U+0327 (COMBINAZIONE DI CEDIGLIA).

    Per ogni personaggio, ci sono due forme normali: forma normale e C
    forma normale D. forma Normale D (NFD) è noto anche come canonica
    decomposizione, e traduce ogni personaggio nella sua scomposta forma.
    Forma normale C (NFC), la prima si applica un canonico di decomposizione, quindi
    si compone di pre-combinato personaggi.

    In aggiunta a queste due forme, ci sono altre due forme normali
    sulla base di compatibilità di equivalenza. In Unicode, alcuni caratteri sono
    supportato, che di norma dovrebbero essere unificata con gli altri personaggi. Per
    esempio, U+2160 (in NUMERI ROMANI) è davvero la stessa cosa U+0049
    (LETTERA MAIUSCOLA LATINA MI). Tuttavia, è supportato in Unicode per
    la compatibilità con i set di caratteri (ad esempio, gb2312).

    La forma normale KD (NFKD) si applica la compatibilità di decomposizione,
    vale a dire sostituire tutti i caratteri di compatibilità con i loro equivalenti. Il
    forma normale KC (NFKC) la prima volta si applica la compatibilità di decomposizione,
    seguito da canonica composizione.

    Anche se due stringhe unicode sono normalizzati e lo stesso aspetto di un
    lettore umano, se uno ha una combinazione di caratteri e non dell’altro,
    essi non possono confrontare alla pari.

    Risolve per me. Semplice e facile.

    OriginaleL’autore Drag0

  14. 3

    Solo aggiungere una variabile encode(‘utf-8’)

    agent_contact.encode('utf-8')
    ha funzionato per me. Grazie.

    OriginaleL’autore Kairat Koibagarov

  15. 3

    Ho sempre messo il codice qui sotto le prime due righe di python file:

    # -*- coding: utf-8 -*-
    from __future__ import unicode_literals

    OriginaleL’autore Pereira

  16. 3

    Sotto la soluzione ha funzionato per me, Appena aggiunto

    u “Stringa”

    (che rappresenta la stringa unicode) prima che la mia stringa.

    result_html = result.to_html(col_space=1, index=False, justify={'right'})
    
    text = u"""
    <html>
    <body>
    <p>
    Hello all, <br>
    <br>
    Here's weekly summary report.  Let me know if you have any questions. <br>
    <br>
    Data Summary <br>
    <br>
    <br>
    {0}
    </p>
    <p>Thanks,</p>
    <p>Data Team</p>
    </body></html>
    """.format(result_html)

    OriginaleL’autore Aravind Krishnakumar

  17. 2

    Ci ha colpito questo errore quando si esegue manage.py migrate in Django localizzato infissi.

    Nostra origine conteneva il # -*- coding: utf-8 -*- dichiarazione, MySQL è stato configurato correttamente per utf8 e Ubuntu ha il language pack appropriato e valori in /etc/default/locale.

    Il problema era semplicemente che l’Django contenitore (si utilizza la finestra mobile) manca la LANG env var.

    Impostazione LANG per en_US.UTF-8 e riavviare il contenitore prima di eseguire di nuovo le migrazioni risolto il problema.

    OriginaleL’autore followben

  18. 1

    Ho appena avuto questo problema, e Google mi ha portato qui, quindi basta aggiungere alle soluzioni generali qui, questo è quello che ha funzionato per me:

    # 'value' contains the problematic data
    unic = u''
    unic += value
    value = unic

    Ho avuto questa idea dopo aver letto Ned presentazione.

    Non ho la pretesa di comprendere appieno perché questo funziona, però. Quindi, se chiunque può modificare questa risposta o inserire un commento per spiegare, io ti apprezzo.

    Qual è la type di valore? prima e dopo questo? Penso che il motivo che funziona è che facendo un unic += value che è la stessa unic = unic + value si sta aggiungendo una stringa unicode e, dove python quindi si presuppone unicode per la conseguente unic cioè il più precise tipo (si pensi a quando si esegue questa operazione a = float(1) + int(1), a diventa un float) e poi value = unic punti value per il nuovo unic oggetto, che succede ad essere unicode.

    OriginaleL’autore pepoluan

  19. 0

    Se avete qualcosa di simile packet_data = "This is data" poi nella riga successiva, subito dopo l’inizializzazione packet_data:

    unic = u''
    packet_data = unic

    OriginaleL’autore Nandan Kulkarni

Lascia un commento