unicodeencodeerror - unicode python 3
UnicodeDecodeError en join (3)
Tengo una lista con algunas cadenas (la mayoría de las cuales obtuve de una base de datos sqlite3):
stats_list = [''Statistik /xc3/xb6ver s/xc3/xa5nger/n'', ''Antal/tS/xc3/xa5ng'', ''1/tCarola - Betlehems Stj/xc3/xa4rna'', ''/n/nStatistik /xc3/xb6ver datak/xc3/xa4llor/n'', ''K/xc3/xa4lla/tAntal'', ''MANUAL/t1'', ''/n/nStatistik /xc3/xb6ver /xc3/xb6nskare/n'', ''Antal/tId'', u''1/tNiclas'']
Cuando trato de unirme a esto:
return ''/n''.join(stats_list)
Me sale este error:
UnicodeDecodeError: ''ascii'' codec can''t decode byte 0xc3 in position 10: ordinal not in range(128)
¿Es posible obtener alguna pista de por qué sucede esto simplemente mirando la lista? Si recorro la lista e imprimiéndola en la pantalla, obtengo esto:
Statistik över sånger Antal Sång 1 Carola - Betlehems Stjärna Statistik över datakällor Källa Antal MANUAL 1 Statistik över önskare Antal Id 1 Niclas
que es exactamente lo que esperaba, y no se muestra ningún error. (Los caracteres especiales son suecos).
EDITAR:
Voy a intentar esto:
return ''/n''.join(i.decode(''utf8'') for i in stats_list)
Pero regresó:
Traceback (most recent call last):
File "./CyberJukebox.py", line 489, in on_stats_to_clipboard
stats = self.jbox.get_stats()
File "/home/nine/dev/python/CyberJukebox/jukebox.py", line 235, in get_stats
return self._stats.get_string()
File "/home/nine/dev/python/CyberJukebox/jukebox.py", line 59, in get_string
return ''/n''.join(i.decode(''utf8'') for i in stats_list)
File "/home/nine/dev/python/CyberJukebox/jukebox.py", line 59, in <genexpr>
return ''/n''.join(i.decode(''utf8'') for i in stats_list)
File "/usr/lib/python2.7/encodings/utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True)
UnicodeEncodeError: ''ascii'' codec can''t encode character u''/xf6'' in position 10: ordinal not in range(128)
EDICION 2:
La solución sugerida funciona para mí en el intérprete. Pero cuando ejecuto el código, no funcionará. No puedo entender esto. Tal vez es algo obvio que me falta, así que estoy pegando todo el método aquí:
def get_string(self):
stats_list = [u''Statistik över sånger/n'', u''Antal/tSång'']
stats = sorted([(v, k) for k, v in self.song_stats.iteritems()], reverse=True)
for row in stats:
line = ''%s/t%s'' % row
stats_list.append(line)
stats_list.append(u''/n/nStatistik över datakällor/n'')
stats_list.append(u''Källa/tAntal'')
stats = sorted([(k, v) for k, v in self.exts_stats.iteritems()])
for row in stats:
line = ''%s/t%s'' % row
stats_list.append(line)
stats_list.append(u''/n/nStatistik över önskare/n'')
stats_list.append(u''Antal/tId'')
stats = sorted([(v, k) for k, v in self.wisher_stats.iteritems() if k != ''''], reverse=True)
for row in stats:
line = ''%s/t%s'' % row
stats_list.append(line)
return ''/n''.join(i.decode(''utf8'') for i in stats_list)
song_stats
, exts_stats
y wisher_stats
son diccionarios de la clase.
Las cadenas están codificadas en UTF-8. Debes .decode
en unicode
:
>>> ''Statistik /xc3/xb6ver s/xc3/xa5nger/n''.decode(''utf-8'')
u''Statistik /xf6ver s/xe5nger/n''
>>> print _
Statistik över sånger
Use la comprensión para realizar esto en todos los elementos:
return ''/n''.join(x.decode(''utf-8'') for x in stats_list)
Python se queja de que no puede convertir la cadena ''Statistik /xc3/xb6ver s/xc3/xa5nger/n''
en una cadena ASCII. Intenta prefijar todas tus cadenas de UNICODE con u
.
stats_list = [u''Statistik /xc3/xb6ver s/xc3/xa5nger/n'', u''Antal/tS/xc3/xa5ng'', u''1/tCarola - Betlehems Stj/xc3/xa4rna'', u''/n/nStatistik /xc3/xb6ver datak/xc3/xa4llor/n'', u''K/xc3/xa4lla/tAntal'', u''MANUAL/t1'', u''/n/nStatistik /xc3/xb6ver /xc3/xb6nskare/n'', u''Antal/tId'', u''1/tNiclas'']
Su problema es probablemente que esté mezclando cadenas Unicode con cadenas de bytes.
El código en "Editar 2" tiene varias cadenas de Unicode añadidas a la stats_list
de stats_list
:
stats_list = [u''Statistik över sånger/n'', u''Antal/tSång'']
Si intenta decodificar estas cadenas de caracteres unicode, obtendrá un UnicodeEncodeError
. Esto porque Python primero intentará usar la codificación predeterminada (generalmente "ascii") para codificar las cadenas antes de intentar decodificarlas . Solo tiene sentido decodificar cadenas de bytes .
Entonces, para empezar, cambie la línea final de la función a:
return ''/n''.join(stats_list)
Ahora necesita verificar si alguna de las otras cadenas que se agregan a la stats_list
son cadenas de bytes , y asegúrese de que se decodifiquen para cadenas unicode correctamente primero.
Así que ponga el print type(line)
después de las tres líneas como esta:
line = ''%s/t%s'' % row
y luego, donde sea que se imprima <type ''str''>
, cambie la siguiente línea por:
stats_list.append(line.decode(''utf-8''))
Por supuesto, si imprime <type ''unicode''>
, no hay necesidad de cambiar la siguiente línea.
Una solución aún mejor aquí sería comprobar cómo se song_stats
los diccionarios song_stats
, exts_stats
y wisher_stats
, y asegurarse de que siempre contengan cadenas de unicode (o cadenas de bytes que solo contengan caracteres ascii).