UnicodeDecodeError для соединения
У меня есть список с некоторыми строками (большинство из которых я получил из базы данных 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']
Когда я пытаюсь присоединиться к нему с помощью
return '\n'.join(stats_list)
Я получаю эту ошибку:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 10: ordinal not in range(128)
Можно ли понять, почему это происходит, просто просматривая список? Если я перейду через список и распечатаю его на экране, я получаю следующее:
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
что и есть то, чего я ожидал, и ошибка не показана. (Специальные символы являются шведскими).
EDIT:
Я попробую:
return '\n'.join(i.decode('utf8') for i in stats_list)
Но он вернулся:
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)
ИЗМЕНИТЬ 2:
Предлагаемое решение работает для меня в интерпретаторе. Но когда я выполняю код, он не будет работать. Я не могу обмотать голову вокруг этого. Может быть, это что-то очевидное, что мне не хватает, поэтому я вставляю весь метод здесь:
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
и wisher_stats
являются словарями в классе.
Ответы
Ответ 1
Вероятно, ваша проблема заключается в том, что вы смешиваете строки unicode с байтовыми строками.
Код в "Редактировании 2" содержит несколько строк юникода, добавленных в stats_list
:
stats_list = [u'Statistik över sånger\n', u'Antal\tSång']
Если вы попытаетесь декодировать эти строки юникода, вы получите UnicodeEncodeError
. Это связано с тем, что Python сначала попытается использовать кодировку по умолчанию (обычно "ascii" ), чтобы кодировать строки, прежде чем пытаться их декодировать. Всегда имеет смысл декодировать байтовые строки.
Итак, для начала измените конечную строку в функции на:
return '\n'.join(stats_list)
Теперь вам нужно проверить, являются ли какие-либо другие строки, которые добавлены в stats_list
, строками байта, и убедитесь, что они сначала правильно декодируются в строки Unicode.
Итак, поставьте print type(line)
после трех строк:
line = '%s\t%s' % row
а затем, где бы он ни печатался <type 'str'>
, измените следующую строку на:
stats_list.append(line.decode('utf-8'))
Конечно, если он печатает <type 'unicode'>
, нет необходимости изменять следующую строку.
Еще лучшее решение здесь - проверить, как создаются словари song_stats
, exts_stats
и wisher_stats
, и убедитесь, что они всегда содержат строки unicode (или байтовые строки, содержащие только символы ascii).
Ответ 2
Строки кодируются в UTF-8. Вам нужно .decode
их на unicode
:
>>> 'Statistik \xc3\xb6ver s\xc3\xa5nger\n'.decode('utf-8')
u'Statistik \xf6ver s\xe5nger\n'
>>> print _
Statistik över sånger
Использовать понимание для выполнения этого для всех элементов:
return '\n'.join(x.decode('utf-8') for x in stats_list)
Ответ 3
Python жалуется, что не может преобразовать строку 'Statistik \xc3\xb6ver s\xc3\xa5nger\n'
в строку ASCII. Попробуйте префикс всех строк UNICODE с помощью 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']