2014-06-29 8 views
28

kiedy próbuję to złączyć, otrzymuję UnicodeDecodeError, gdy pole zawiera "ñ" lub "". Jeśli pole zawierające "ñ" lub "" jest ostatnim, nie otrzymuję błędu.UnicodeDecodeError: Kodek 'ascii' nie może dekodować bajtu 0xc3 w pozycji 23: porządkowy nie jest w zakresie (128)

#... 

nombre = fabrica 
nombre = nombre.encode("utf-8") + '-' + sector.encode("utf-8") 
nombre = nombre.encode("utf-8") + '-' + unidad.encode("utf-8") 

#... 

return nombre 

jakiś pomysł? Wielkie dzięki!

+0

Możliwy duplikat [Python - 'ascii' codec nie może dekodować bajt] (http://stackoverflow.com/questions/ 9644099/python-ascii-codec-cant-decode-byte) – bummi

Odpowiedz

36

Kodowanie do UTF-8, następnie re - kodowanie do UTF-8. Python można to zrobić tylko wtedy, gdy uprzednio dekoduje ponownie na Unicode, ale musi użyć kodek domyślny ASCII:

>>> u'ñ' 
u'\xf1' 
>>> u'ñ'.encode('utf8') 
'\xc3\xb1' 
>>> u'ñ'.encode('utf8').encode('utf8') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128) 

Nie przechowywać kodowanie; pozostaw kodowanie do UTF-8 zamiast do ostatniej możliwej chwili. Łącz zamiast wartości Unicode.

Można użyć str.join() (lub raczej unicode.join()) tutaj, aby złączyć te trzy wartości z kresek pomiędzy:

nombre = u'-'.join(fabrica, sector, unidad) 
return nombre.encode('utf-8') 

ale nawet tutaj kodowania może być zbyt wcześnie.

Zasada kciuka: dekodowanie w momencie otrzymania wartości (jeśli nie są to wartości Unicode dostarczone przez API), koduj tylko wtedy, gdy musisz (jeśli docelowy interfejs API nie obsługuje bezpośrednio wartości Unicode).

+0

Myślę, że kluczowa jest tutaj zasada. Może to być sformułowanie "zakodować i odkodować tylko na granicach API, a następnie tylko wtedy, gdy musisz". –

0

To rozwiązanie pracował dla mojego przypadku

zmian

my_str = str(my_str) #Basically it removes encoding 
+0

'str (my_str)' może go nie rozwiązać: 'UnicodeDecodeError: kodek 'ascii' nie może dekodować bajtu 0xc3 w pozycji 1253: porządkowy nie w zakresie (128)' – rafaelvalle

1

Kiedy masz UnicodeEncodeError, oznacza to, że gdzieś w kodzie bezpośrednio przekonwertować ciąg bajtów do jednej Unicode. Domyślnie w Pythonie 2 używa kodowania ascii, a kodowanie utf8 w Python3 (oba mogą się nie powieść, ponieważ nie każdy bajt jest ważny w kodowaniu).

Aby tego uniknąć, należy użyć jawnego dekodowania.

Jeśli możesz mieć 2 różne kodowania w pliku wejściowym, jeden z nich akceptuje dowolny bajt (np. UTF8 i Latin1), możesz spróbować najpierw przekonwertować ciąg z pierwszym i użyć drugiego, jeśli wystąpi UnicodeDecodeError.

def robust_decode(bs): 
    '''Takes a byte string as param and convert it into a unicode one. 
First tries UTF8, and fallback to Latin1 if it fails''' 
    cr = None 
    try: 
     cr = bs.decode('utf8') 
    except UnicodeDecodeError: 
     cr = bs.decode('latin1') 
    return cr 

Jeśli nie wiesz oryginalne kodowanie i nie obchodzi za nieprzestrzeganie znaków ASCII, można ustawić parametr opcjonalny errors metody do replacedecode. Wszelkie bajt naruszającym przepisy zostaną zastąpione (od standardowej dokumentacji biblioteki):

Replace with a suitable replacement character; Python will use the official U+FFFD REPLACEMENT CHARACTER for the built-in Unicode codecs on decoding and ‘?’ on encoding.

bs.decode(errors='replace') 
+0

To nie jest bezpośrednio odpowiedź na obecne pytanie, ale na [ ten jeden] (http://stackoverflow.com/q/42410322/3545273), który został zamknięty jako duplikat.Przynajmniej jest powiązany z powodu UnicodeDecodeError, a użytkownicy szukający błędu znajdą tę odpowiedź ... –

Powiązane problemy