为什么在使用python2.7将unicode字符插入sqlite3数据库时会得到额外的转义符?

2024-10-03 06:29:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我查询一个API,得到一个json blob,值如下:

{
    ...
    "Attribute" : "Some W\u00e9irdness", 
    ...
}

(当然,正确的值是'Some weirdness')

我将这个值和其他一些东西一起添加到我想添加到sqlite3数据库的字段列表中。列表如下:

^{pr2}$

我注意到我们已经经历了从\x00e9到\xe9的转换,我不知道为什么会这样,但我希望这不重要…只是不同的unicode编码。在

在尝试插入sqlite表之前,我对列表进行“stringatize”(请参见下面的函数)并使其成为一个元组:

('', '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中使用字符串插值。可是,我想不出该怎么办?”当每个记录的字段数可能随时间而变化时,我希望代码更灵活,如果我添加字段,则不必返回并在其中添加问号。(如果你知道更好的方法,我洗耳恭听,但可能是为了另一篇文章。)

为了解决问题,我打印了格式化的insertion sql语句,只看到一个反斜杠:

INSERT OR REPLACE INTO roster VALUES ('', '203', '', '', 'True', 'W\xe9irdness', '', 'Some', '', '', 'Some W\xe9irdness', '', 'Some W\xe9irdness', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '')

这和我在上面的列表中看到的一样,所以我很困惑。也许这被解释为带有反斜杠的字符串,而xe9只是被当作ascii文本来处理。下面是我用来准备插入列表的stringatize函数:

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工作表中,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(我的元组)有关,而u“实际上不再是unicode的象征。在


Tags: in列表newsqldatetimemyunicodecell
1条回答
网友
1楼 · 发布于 2024-10-03 06:29:22
"Some W\u00e9irdness"
"Some Wéirdness"

是完全相同的值Some Wéirdness的同样有效的JSON字符串文本形式。在

^{pr2}$

I notice that we've already undergone a switch from \x00e9 to \xe9, and I'm not sure why that is yet, but I was hoping it didn't matter...it's just a different unicode encoding.

没有开关,也没有编码,字符串仍然是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字符串文本没有任何反斜杠转义符的概念,因此在Python Unicode字符串文本中表示é\xE9在SQL中只意味着反斜杠、字母xE和数字9。在

虽然有适当的方法来编码一个字符串以适应一个SQL字符串文本,但是您应该避免这样做,因为得到正确的字符串不是简单的,得到错误的字符串是一个安全问题。相反,请忽略“stringatizing”,只需将原始值作为参数传递到数据库:

cur.execute(
    'INSERT OR REPLACE INTO roster VALUES (?, ?, ?, ?, ....)',
    my_list
)

相关问题 更多 >