我有一个 python 程序,在 sqlite3 中存储一些数据,我想在不同的操作系统中使用它。
在 Windows 7 中该程序运行良好,但在 Ubuntu 12.04 中则不然。
问题是:当我在 sqlite 数据库中存储一个空元组(作为 "".join( ... )
中的字符串)然后在 Windows 中读回它时,我得到一个空的tuple ()
,而在 Ubuntu 中我得到 None
。
我的测试代码是:
import sqlite3
import os
def adapt_tuple(tpl):
return " ".join(str(n) for n in tpl)
def get_tuple(s):
return tuple([int(x) for x in s.split()])
emptytuple=()
goodtuple=(1,2)
sqlite3.register_adapter(tuple,adapt_tuple)
sqlite3.register_converter("tuple_of_ints",get_tuple)
myconn=sqlite3.connect('test.db',detect_types=sqlite3.PARSE_DECLTYPES)
myconn.execute("""CREATE TABLE test(number int, tuple tuple_of_ints);""")
goodentry=(1,goodtuple)
emptyentry=(2,emptytuple)
myconn.execute("""INSERT INTO test VALUES (?,?);""", goodentry)
myconn.execute("""INSERT INTO test VALUES (?,?);""", emptyentry)
for row in myconn.execute("""SELECT * FROM test;"""):
print row
myconn.close()
os.remove('test.db')
这给了我一个输出:
(1, (1, 2))
(2, ())
在窗口中 和:
(1, (1, 2))
(2, None)
在 Ubuntu 中。
我已经查过了
get_tuple(adapt_tuple(emptytuple))
在两个系统中给出相同的输出()
,因此它必须与通过sqlite3有关。
Python中sys.version_info
的输出在两个系统中是相同的,sqlite3.version
也是如此,所以我很确定这与操作系统。
总而言之,我的问题是: 为什么会发生这种情况?以及如何让 Ubuntu 版本最后返回一个空元组?
感谢您的回复。 苹果。
注意
我本来应该提到,如果我打印我的 adapt_tuple
输出,我会在两个操作系统上得到 ""
。
最佳答案
看起来您的一个 sqlite
版本将适配器返回中的空字符串视为 NULL,并且也许您有不同的 sqlite
版本这可以解释不同的行为。
如果是这种情况,那么您需要修改适配器以便不返回空字符串。然后还需要调整转换器以处理新格式。这是一个示例:
def adapt_tuple(tpl):
return repr(tpl)
def get_tuple(s):
if len(s) > 2:
return tuple(int(x) for x in s[1:-1].split(','))
return ()
实际问题与register_converter
有关,它依赖于sqlite3_column_blob
。后者对于零长度 BLOB 返回 NULL(请参阅 sqlite's documentation )。然后在pysqlite
的代码中有一个如下形式的检查:
if (!sqlite3_column_blob(...)) converted_col = Py_None;
因此,永远不会为空字符串调用您的转换器,并且不会返回 None。
问题是 pysqlite
取决于 sqlite3_column_blob
的行为,这可能会在 sqlite
版本之间发生变化。事实上,确实如此。从 sqlite 3.7.3 开始,sqlite3_column_blob
进行了修改以符合文档。在此之前,它不会对空 blob 返回 NULL。因此,为了保持一致,请确保您的适配器永远不会返回空字符串。
关于python - 在linux上与windows上不同的sqlite中存储空的python元组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15055189/