我正在尝试使用twisted.enterprise.adbapi.ConnectionPool
创建一个内存中的sqlite数据库。
以下代码按预期工作:
#! /usr/bin/env python
from twisted.internet.task import react
from twisted.internet import defer
from twisted.enterprise.adbapi import ConnectionPool
sql_init = """
CREATE TABLE ajxp_changes ( seq INTEGER PRIMARY KEY AUTOINCREMENT, node_id NUMERIC, type TEXT, source TEXT, target TEXT, deleted_md5 TEXT );
CREATE TABLE ajxp_index ( node_id INTEGER PRIMARY KEY AUTOINCREMENT, node_path TEXT, bytesize NUMERIC, md5 TEXT, mtime NUMERIC, stat_result BLOB);
CREATE TRIGGER LOG_INSERT AFTER INSERT ON ajxp_index BEGIN INSERT INTO ajxp_changes (node_id,source,target,type) VALUES (new.node_id, "NULL", new.node_path, "create"); END;
"""
sql_insert = "INSERT INTO ajxp_index (node_path,bytesize,md5,mtime,stat_result) VALUES (?,?,?,?,?);"
sql_file_path = "/tmp/test.sqlite"
@react
@defer.inlineCallbacks
def main(reactor):
cp = ConnectionPool("sqlite3", sql_file_path, check_same_thread=False)
yield cp.runInteraction(lambda c, s: c.executescript(s), sql_init)
params = (
"/tmp/test.txt",
"64",
"5d41402abc4b2a76b9719d911017c592",
2832345,
"xxxxxx"
)
yield cp.runOperation(sql_insert, params)
但是,将sql_file_path="/tmp/test.sqlite
替换为sql_file_path=":memory:"
突然导致脚本失败,并带有以下回溯:
$ python test.py
main function encountered error
Traceback (most recent call last):
File "/Users/lthibault/.pyenv/versions/3.5.3/lib/python3.5/site-packages/twisted/internet/defer.py", line 500, in errback
self._startRunCallbacks(fail)
File "/Users/lthibault/.pyenv/versions/3.5.3/lib/python3.5/site-packages/twisted/internet/defer.py", line 567, in _startRunCallbacks
self._runCallbacks()
File "/Users/lthibault/.pyenv/versions/3.5.3/lib/python3.5/site-packages/twisted/internet/defer.py", line 653, in _runCallbacks
current.result = callback(current.result, *args, **kw)
File "/Users/lthibault/.pyenv/versions/3.5.3/lib/python3.5/site-packages/twisted/internet/defer.py", line 1357, in gotResult
_inlineCallbacks(r, g, deferred)
--- <exception caught here> ---
File "/Users/lthibault/.pyenv/versions/3.5.3/lib/python3.5/site-packages/twisted/internet/defer.py", line 1299, in _inlineCallbacks
result = result.throwExceptionIntoGenerator(g)
File "/Users/lthibault/.pyenv/versions/3.5.3/lib/python3.5/site-packages/twisted/python/failure.py", line 393, in throwExceptionIntoGenerator
return g.throw(self.type, self.value, self.tb)
File "test.py", line 35, in main
yield cp.runOperation(sql_insert, params)
File "/Users/lthibault/.pyenv/versions/3.5.3/lib/python3.5/site-packages/twisted/python/threadpool.py", line 250, in inContext
result = inContext.theWork()
File "/Users/lthibault/.pyenv/versions/3.5.3/lib/python3.5/site-packages/twisted/python/threadpool.py", line 266, in <lambda>
inContext.theWork = lambda: context.call(ctx, func, *args, **kw)
File "/Users/lthibault/.pyenv/versions/3.5.3/lib/python3.5/site-packages/twisted/python/context.py", line 122, in callWithContext
return self.currentContext().callWithContext(ctx, func, *args, **kw)
File "/Users/lthibault/.pyenv/versions/3.5.3/lib/python3.5/site-packages/twisted/python/context.py", line 85, in callWithContext
return func(*args,**kw)
File "/Users/lthibault/.pyenv/versions/3.5.3/lib/python3.5/site-packages/twisted/enterprise/adbapi.py", line 477, in _runInteraction
compat.reraise(excValue, excTraceback)
File "/Users/lthibault/.pyenv/versions/3.5.3/lib/python3.5/site-packages/twisted/python/compat.py", line 467, in reraise
raise exception.with_traceback(traceback)
File "/Users/lthibault/.pyenv/versions/3.5.3/lib/python3.5/site-packages/twisted/enterprise/adbapi.py", line 467, in _runInteraction
result = interaction(trans, *args, **kw)
File "/Users/lthibault/.pyenv/versions/3.5.3/lib/python3.5/site-packages/twisted/enterprise/adbapi.py", line 486, in _runOperation
trans.execute(*args, **kw)
sqlite3.OperationalError: no such table: ajxp_index
#! /usr/bin/env python
import sqlite3
conn = sqlite3.connect(":memory:")
conn.executescript(sql_init)
conn.execute(
sql_insert,
("/tmp/test.txt", "64", "5d41402abc4b2a76b9719d911017c592", 2832345, "xxxxxx"),
)
结论:问题源于twisted.enterprise.adbapi.ConnectionPool
ConnectionPool
方法来运行INSERT
语句。不可否认,此时我正在抓住稻草,但我认为这个问题可能源于我使用runOperation
。我决定使用runInteraction
和runQuery
复制原始示例。
yield cp.runOperation(sql_insert, params)
的以下替换也会失败并出现相同的错误。
yield cp.runInteraction(lambda c, s, p: c.execute(s), sql_insert, params)
yield cp.runQuery(sql_insert, params)
重要的是,将sqlite数据库路径从:memory:
更改为持久存储上的某个路径,runInteraction
和runQuery
都按预期工作。
结论:问题与在Twisted中使用内存中的sqlite数据库有关。
有什么想法吗?
答案 0 :(得分:0)
好的,事实证明,每次调用查询方法时,ConnectionPool
都会尝试连接到:memory:
,因此每次都会重新创建数据库。
解决方案似乎是编写一个包含sqlite3的DB-API v.20模块,并在调用connect函数时始终返回相同的:memory:
连接。