连接时的Unicode解码错误

13 投票
3 回答
11329 浏览
提问于 2025-04-17 08:14

我有一个包含一些字符串的列表(大部分是我从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

这正是我所期待的,并且没有显示错误。(这些特殊字符是瑞典语的)。

编辑:

我尝试了这个:

   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_statsexts_statswisher_stats都是这个类中的字典。

3 个回答

1

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

这些字符串是用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)
11

你的问题可能是因为你把unicode字符串和字节字符串混在一起了。

在“编辑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_statsexts_statswisher_stats是怎么创建的,确保它们始终包含unicode字符串(或者只包含ascii字符的字节字符串)。

撰写回答