我查询API并获取具有以下值的json blob:
{
...
"Attribute" : "Some W\u00e9irdness",
...
}
(正确的值,当然是'SomeWéirdness')
我将该值与其他一些内容一起添加到我想添加到sqlite3数据库的字段列表中。该列表如下所示:
[None, 203, None, None, True, u'W\xe9irdness', None, u'Some', None, None, u'Some W\xe9irdness', None, u'Some W\xe9irdness', None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None]
我注意到我们已经经历了从\ x00e9到\ xe9的切换,我不知道为什么会这样,但我希望它没关系......它只是一个不同的unicode编码。
在尝试插入sqlite表之前,我'对该列表进行了字符串化(参见下面的函数)并将其设为元组:
('', '203', '', '', 'True', 'W\xe9irdness', '', 'Some', '', '', 'Some W\xe9irdness', '', 'Some W\xe9irdness', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '')
然后我做了插入:
my_tuple = tuple(val for val in my_utils.stringatize(my_list))
sql = "INSERT OR REPLACE INTO roster VALUES %s" % repr(my_tuple)
cur.execute(sql)
当我稍后使用SELECT语句检索它时,该值会添加一个额外的转义(反斜杠)字符:
u'Some W\\xe9irdness'
首先,我已经知道我不应该在sqlite中使用字符串插值。但是,当每个记录的字段数量随时间变化而且我希望代码变得灵活而不必返回并在那里添加问号(如果我添加)时,我无法弄清楚如何使用?领域。 (如果你知道更好的方法,我会全力以赴,但这可能是另一篇文章。)
要进行故障排除,我打印格式化的插入sql语句,我只看到一个反斜杠:
INSERT OR REPLACE INTO roster VALUES ('', '203', '', '', 'True', 'W\xe9irdness', '', 'Some', '', '', 'Some W\xe9irdness', '', 'Some W\xe9irdness', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '')
这与我上面的列表看起来相同,所以我很困惑。也许这会被解释为带有反斜杠的字符串,必须将其转义并且xe9才会被视为ascii文本。这是我用来准备插入列表的字符串化函数:
def stringatize(cell_list, encoding = 'raw_unicode_escape', delete_quotes = False):
"""
Converts every 'cell' in a 'row' (generally something extracted from
a spreadsheet) to a unicode, then returns the list of cells (with all
strings now, of course).
"""
stringatized_list = []
for cell in cell_list:
if isinstance(cell, (datetime.datetime)):
new = cell.strftime("%Y-%m-%dT%H:%M:%S")
elif isinstance(cell, (datetime.date)):
new = cell.strftime("%Y-%m-%d")
elif isinstance(cell, (datetime.time)):
new = cell.strftime("%H:%M:%S")
elif isinstance(cell, (int, long)):
new = str(cell)
elif isinstance(cell, (float)):
new = "%.2f" % cell
elif cell == None:
new = ""
else:
new = cell
if delete_quotes:
new = new.replace("\"","")
my_unicode = new.encode(encoding)
stringatized_list.append(my_unicode)
return stringatized_list
我很欣赏你在这方面给我的任何想法。目标是最终将此值转储到Excel工作表中,该工作表可以使用Unicode,因此应该正确显示该值。
编辑:为了回应@ CL的询问,我尝试从我的stringatize函数中删除'encode'行。
现在结束如下:
#my_unicode = new.encode(encoding)
my_unicode = new
stringatized_list.append(my_unicode)
return stringatized_list
新的sql看起来像这样(以下是我尝试执行时得到的回溯):
INSERT OR REPLACE INTO roster VALUES ('', u'203', u'', u'', 'True', u'W\xe9irdness', '', u'Some', '', '', u'Some W\xe9irdness', '', u'Some W\xe9irdness', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '')
Traceback (most recent call last):
File "test.py", line 80, in <module>
my_call
File redacted.py, line 102, in my_function
cur.execute(sql)
sqlite3.OperationalError: near "'203'": syntax error
我的意思是将该数字转换为字符串。我怀疑它与我正在做的repr(my_tuple)有关,你实际上不再象征着unicode了。
答案 0 :(得分:2)
"Some W\u00e9irdness"
"Some Wéirdness"
同样有效的JSON字符串文字形式具有完全相同的值Some Wéirdness
。
u'W\xe9irdness'
我注意到我们已经经历了从\ x00e9到\ xe9的切换,我不知道为什么会这样,但我希望它没关系......它只是一个不同的unicode编码。
没有开关,也没有编码,字符串仍为Some Wéirdness
。
您刚刚从Python打印了字符串,而在Python字符串文字中,有一个JSON没有的\xNN
表单,\u00NN
的简写。
my_tuple = tuple(val for val in my_utils.stringatize(my_list))
sql = "INSERT OR REPLACE INTO roster VALUES %s" % repr(my_tuple)
cur.execute(sql)
不要这样做。由repr
生成的Python元组文字与SQL值列表的格式完全不同。特别是,SQL字符串文字没有反斜杠转义的任何概念,因此在SQL Unicode字符串文字中表示\xE9
的{{1}}在SQL中仅表示反斜杠,字母{{1} },é
和数字x
。
虽然有适当的方法来编码一个字符串以适应SQL字符串文字,但你应该避免这种情况,因为正确的方法并不简单并且出错是一个安全问题。相反,忘记'stringatizing'并将原始值作为参数传递给数据库:
E