[Twisted-Python] How to correctly run Sqlite with Twisted?
Werner Thie
werner at thieprojects.ch
Tue Sep 19 15:50:23 MDT 2017
Aloha Goffi
I'm using minimal code like the one below for MySQL interaction, should be easy to transition this to SQLite
from twisted.internet import reactor, task, defer
from store import Store
#debugging func, printing the result on the console
def _transformResult(result):
## print '####', result
if result:
return result[0] #unpack the list
else:
return None
class Somestore(object):
name = "somestore"
def __init__(self, dbapiName, **params):
self.store = Store(dbapiName, **params)
ka = task.LoopingCall(self.keepAlive) #db keepalive
ka.start(307)
def dbdisconn(self, reason):
print 'db disconnected for ', reason
def keepAlive(self):
try:
d = self.store.runQuery('SELECT 1')
d.addErrback(self.dbdisconn)
except:
pass
else:
pass #do whatever MUST occur here in all cases
def getTableCount(self):
d = self.store.runQuery('SELECT tables FROM user WHERE servername = %s', 'total')
d.addCallback(_transformResult)
d.addErrback(self.dbdisconn)
return d
def setUserCount(self, waiting, playing, tables):
d = self.store.runOperation('UPDATE user SET waiting = %s, playing = %s, tables = %s WHERE servername = %s', waiting, playing, tables, self.loggername)
d.addErrback(self.dbdisconn)
return d
module store.py
from itertools import izip
from twisted.enterprise import adbapi
using it with canned queries like
class Store(object):
def __init__(self, dbapiName, **params):
self.__pool = adbapi.ConnectionPool(dbapiName, **params)
print self.__pool.__getstate__()
self.runOperation('SET autocommit = %s', 1)
def runQuery(self, query, *args):
d = self.__pool.runInteraction(self.mapQuery, query, args)
return d
def runInsert(self, query, *args):
def mapQ(curs, query, *args):
try:
curs.execute(query, *args)
except adbapi.ConnectionLost:
print
print '++++++++++++ rerunning query'
print
curs.execute(query, *args) #simply resend query, assuming cp_reconnect=True
return {'lastrowid': -1}
return {'lastrowid': curs.lastrowid}
d = self.__pool.runInteraction(mapQ, query, args)
return d
def mapQuery(self, curs, query, *args):
try:
curs.execute(query, *args)
except adbapi.ConnectionLost:
curs.execute(query, *args) #simply resend query, assuming cp_reconnect=True
result = curs.fetchall()
columns = [d[0] for d in curs.description]
return [dict(zip(columns, r)) for r in result]
def runOperation(self, query, *args):
d = self.__pool.runOperation(query, args)
return d
On 9/19/2017 10:59 AM, Goffi wrote:
> Hello,
>
> I'm using Sqlite3 module through Twisted's enterpirse.adbapi, I create the
> ConnectionPool instance like this:
>
> self.dbpool = ConnectionPool("sqlite3", db_filename,
> check_same_thread=False)
>
> You can see the code at https://repos.goffi.org/sat/file/tip/src/memory/sqlite.py
>
> Sometime, the writing is failing with following exception:
>
> Failure instance: Traceback: <class 'sqlite3.OperationalError'>: database is
> locked
>
> So I wonder if the database is correctly used, did anybody experienced
> something similar with Twisted and Sqlite ?
>
> Should I just augment timeout as advised at https://stackoverflow.com/a/
> 8618328? Looks like more a workaround than a clean solution.
>
> Python 2 documentation doesn't talk about check_same_thread argument, but
> Python 3 at https://docs.python.org/3.5/library/sqlite3.html#sqlite3.connect
> says that writing operation should be serialized by the user (I thought it was
> the default as said in https://sqlite.org/threadsafe.html), how should I
> achieve that?
>
> Also PRAGMA are not working (specially "PRAGMA foreign_keys = ON"), I guess
> because of multi-threading, what is the good way to activate foreign_keys for
> all following request?
>
> Thanks in advance
>
> Goffi
>
> _______________________________________________
> Twisted-Python mailing list
> Twisted-Python at twistedmatrix.com
> https://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
More information about the Twisted-Python
mailing list