我将utf-8编码为 \ u2013 之类的字符,然后再插入SQLite。
当我用SELECT将它们拉出来时,它们又以未编码的形式返回,所以如果我想对它们做任何事情,我需要对它们进行重新编码。在这种情况下,我想将行写入CSV。在将行写入CSV之前,我想首先将超链接添加到值为“http”的任何行。一些值将是整数,日期等,所以我做了以下条件表达式 - 列表理解组合:
row = ['=HYPERLINK("%s")' % cell if 'http' in str(cell) else cell for cell in row].
str()
操作会产生众所周知的:
UnicodeEncodeError:'ascii'编解码器无法对字符u'\ u2013'进行编码 位置15:序数不在范围内(128)错误。
我需要的是再次执行.encode('utf-8')
编码,但仅限于列表中以字符串开头的那些元素。以下内容不起作用(因为并非所有元素都是字符串):
['=HYPERLINK("%s")' % cell if 'http' in str(cell).encode('utf8') else cell.encode('utf8') for cell in row]
TLDR:如何扩展/修改列表推导以仅对元素进行编码(如果它是字符串?)
答案 0 :(得分:1)
一般来说,尽可能使用unicode,并编码unicode
字节(即str
s)仅在必要时,例如将输出写入网络
套接字或文件。
不要将str
与unicode
混合 - 尽管Python2允许这样做,
它会导致Python2使用str
编解码器隐式地将unicode
转换为ascii
,反之亦然。如果隐式编码或解码失败,则会分别得到UnicodeEncodingError或UnicodedDecodingError,例如您正在看到的那个。
由于cell
是unicode,因此请使用u'=HYPERLINK("{}")'.format(cell)
或u'=HYPERLINK("%s")' % cell
代替'=HYPERLINK("%s")' % cell
。 (请注意,如果cell
包含双引号,您可能需要对cell
进行网址编码。
row = [u'=HYPERLINK("{}")'.format(cell)
if isinstance(cell, unicode) and cell.startswith(u'http') else cell
for cell in row]
稍后,当/如果您需要将row
转换为str
时,您可以使用
row = [cell.encode('utf-8') if isinstance(cell, unicode) else str(cell)
for cell in row]
或者,首先将row
中的所有内容转换为str
:
row = [cell.encode('utf-8') if isinstance(cell, unicode) else str(cell)
for cell in row]
然后你可以使用
row = ['=HYPERLINK("{}")'.format(cell) if cell.startswith('http') else cell
for cell in row]
同样,由于row
包含cell
是unicode,因此执行测试
if u'http' in cell
使用unicode
u'http'
代替str
'http'
,或者更好,
if isinstance(cell, unicode) and cell.startswith(u'http')
虽然如果你在这里保留'http'
没有错误(因为ascii
编解码器可以解码0-127范围内的字节),不管怎样,最好使用u'http'
符合规则永远不会混合str
和unicode
,并支持精神清晰。