2012-03-10 7 views
94

Sono davvero confuso. Ho provato a codificare ma l'errore ha detto can't decode....Python - Il codec 'ascii' non può decodificare il byte

>>> "你好".encode("utf8") 
Traceback (most recent call last): 
File "<stdin>", line 1, in <module> 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128) 

so come evitare l'errore con "u" prefisso sulla corda. Mi sto solo chiedendo perché l'errore è "non può decodificare" quando è stata chiamata la codifica. Cosa sta facendo Python sotto il cofano?

risposta

141
"你好".encode('utf-8') 

encode converte un oggetto unicode a un oggetto string. Ma qui lo hai invocato su un oggetto string (perché non hai la u). Quindi python deve prima convertire lo string in un oggetto unicode. Così fa l'equivalente di

"你好".decode().encode('utf-8') 

Ma la decodifica fallisce perché la stringa non è valida ascii. Ecco perché ti viene chiesto di non essere in grado di decodificare.

+29

Quindi qual è la soluzione? Soprattutto se non ho una stringa letterale, ho solo un oggetto stringa. –

+2

@JonTirsen, non dovresti codificare un oggetto stringa. Un oggetto stringa è già codificato. Se è necessario modificare la codifica, è necessario decodificarla in una stringa unicode e quindi codificarla come codifica desiderata. –

+17

Quindi per dirlo chiaramente dall'alto puoi '" 你好 ".decode ('utf-8'). Encode ('utf-8')' – deinonychusaur

44

Sempre codifica da unicode a byte.
In questa direzione, è possibile scegliere la codifica.

>>> u"你好".encode("utf8") 
'\xe4\xbd\xa0\xe5\xa5\xbd' 
>>> print _ 
你好 

L'altro modo è quello di decodificare da byte a unicode.
In questa direzione, devi sapere che cos'è la codifica.

>>> bytes = '\xe4\xbd\xa0\xe5\xa5\xbd' 
>>> print bytes 
你好 
>>> bytes.decode('utf-8') 
u'\u4f60\u597d' 
>>> print _ 
你好 

Questo punto non può essere sottolineato abbastanza. Se vuoi evitare di giocare a unicode "whack-a-mole", è importante capire cosa sta succedendo a livello di dati. Qui è spiegato un altro modo:

  • Un oggetto unicode è già decodificato, non si desidera chiamare decode su di esso.
  • Un oggetto testuale è già codificato, non si desidera mai chiamare encode su di esso.

Ora, vedendo .encode su una stringa di byte, Python 2 tenta prima di convertire in modo implicito in testo (un oggetto unicode). Allo stesso modo, vedendo .decode su una stringa unicode, Python 2 tenta implicitamente di convertirlo in byte (un oggetto str).

Queste conversioni implicite sono il motivo per cui è possibile ottenere UnicodeDecodeError quando hai chiamato encode. È perché la codifica di solito accetta un parametro di tipo unicode; quando si riceve un parametro str, c'è una decodifica implicita in un oggetto di tipo unicode prima di ricodificarlo con un'altra codifica. Questa conversione sceglie un decodificatore 'ascii' predefinito , fornendo l'errore di decodifica all'interno di un encoder.

Infatti, in Python 3 i metodi str.decode e bytes.encode non esistono nemmeno. La loro rimozione fu un tentativo [controverso] di evitare questa confusione comune.

... o qualsiasi codifica sys.getdefaultencoding() menzioni; Di solito questo è 'ascii'

+0

Quindi intendi che Python decodifica il bytestring prima della codifica? – thoslin

+0

@thoslin esattamente, ho aggiunto più dettagli. – wim

+0

Che cos'è _, e perché le frasi di stampa mancano di parentesi? – NoBugs

6

Se si sta utilizzando Python < 3, è necessario dire all'interprete che il vostro string literal is Unicode by prefixing it with a u:

Python 2.7.2 (default, Jan 14 2012, 23:14:09) 
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> "你好".encode("utf8") 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128) 
>>> u"你好".encode("utf8") 
'\xe4\xbd\xa0\xe5\xa5\xbd' 

Ulteriori letture: Unicode HOWTO.

+3

Se stai codificando una stringa, perché genera un errore di decodifica? – MxyL

1

È possibile utilizzare u"你好".encode('utf8') per codificare una stringa Unicode. Ma se vuoi rappresentare "你好", dovresti decodificarlo. Proprio come:

"你好".decode("utf8") 

Otterrete quello che volete. Forse dovresti imparare di più sulla codifica & decodifica.

33

Si può provare questo

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

O

Si può anche provare a seguito

Add seguente riga nella parte superiore del file .py.

# -*- coding: utf-8 -*- 
+5

Messing con la codifica da Python, mentre possibile, è un'idea davvero pericolosa. * * * Causerà problemi imprevisti lungo la linea se lo fai. Ottieni i tuoi dati, invece, come descritto nelle altre risposte. – davidism

+1

@davidism - perché/come? – Xodarap777

1

Nel caso in cui hai a che fare con Unicode, a volte invece di encode('utf-8'), si può anche provare a ignorare i caratteri speciali, ad esempio,

"你好".encode('ascii','ignore') 

o come something.decode('unicode_escape').encode('ascii','ignore') as suggested here.

Non particolarmente utile in questo esempio, ma può funzionare meglio in altri scenari quando non è possibile convertire alcuni caratteri speciali.

In alternativa è possibile considerare replacing particular character using replace().