UnicodeDecodeError при соединении - PullRequest
13 голосов
/ 13 декабря 2011

У меня есть список с некоторыми строками (большинство из которых я извлек из базы данных 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 являются словарями в классе.

Ответы [ 3 ]

11 голосов
/ 13 декабря 2011

Возможно, ваша проблема в том, что вы смешиваете строки юникода с байтовыми строками.

В коде "Edit 2" есть несколько строк unicode , добавляемых к stats_list:

stats_list = [u'Statistik över sånger\n', u'Antal\tSång']

Если вы попытаетесь декодировать эти строки Unicode, вы получите 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).

7 голосов
/ 13 декабря 2011

Строки кодируются в 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)
1 голос
/ 13 декабря 2011

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']
...