我有一个MySQL数据库,其中包含多个具有如下结构的表:
CREATE TABLE IF NOT EXISTS `table1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`key1` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE (`key1`)
);
在我使用Twisted框架的Python程序中,我需要执行一系列这些表中的每一个的操作几乎相同:
key
列中是否存在给定值。id
。id
。由于操作本质上是相同的,因此这很有意义由具有表和键名的函数执行的操作,以及该值作为参数并返回ID。
我该怎么做?我做不到
import MySQLdb
from twisted.python import log
from twisted.enterprise.adbapi import ConnectionPool
from twisted.internet.defer import inlineCallbacks
class ReconnectingConnectionPool(ConnectionPool):
def _runInteraction(self, interaction, *args, **kw):
try:
return ConnectionPool._runInteraction(
self, interaction, *args, **kw)
except MySQLdb.OperationalError as e: # pylint: disable=no-member
if e[0] not in (2003, 2006, 2013):
raise e
conn = self.connections.get(self.threadID())
self.disconnect(conn)
# Try the interaction again
return ConnectionPool._runInteraction(
self, interaction, *args, **kw)
dbh = ReconnectingConnectionPool(
'MySQLdb',
db='database',
user='user',
passwd='password'
)
@inlineCallbacks
def get_id(table, column, entry):
try:
r = yield dbh.runQuery("SELECT `id` FROM `{}` WHERE `{}` = '{}'".format(table, column, entry))
if r:
id = r[0][0]
else:
yield dbh.runQuery("INSERT INTO `{}` (`{}`) VALUES ('{}')".format(table, column, entry))
r = yield dbh.runQuery('SELECT LAST_INSERT_ID()')
id = int(r[0][0])
except Exception as e:
log.msg(e)
id = 0
return id
因为函数get_id
是一个生成器,并且它们不能直接返回值。
我应该使用defer.returnValue(id)
代替return id
吗?还是我应该使用dbh.runQuery('query').addCallback(get_result)
其中get_result
是这样的函数
def get_result(value):
return value
还是我应该做其他事情?
get_id
函数本身将返回deferred
,因为您使用inlineCallbacks
包装它。
然后您使用以下命令调用函数:
get_id().addCallback(your_callback_to_retrive_the_id)
在get_id
函数中,如果您使用的是python3,则可以使用return
或defer.returnValue
语句返回结果。
在python2中,您只能使用defer.returnValue
from __future__ import print_function
from twisted.internet import reactor
from twisted.internet.defer import Deferred, returnValue, inlineCallbacks
def runQuery(query):
# suppose this will fetch the result from database
d = Deferred()
# simulate the delay waiting for the database to give the results
# using reactor.callLater
reactor.callLater(0.3, d.callback, 1); # 1 here is the (result)
return d
@inlineCallbacks
def get_id(table, column, entry):
r = yield runQuery("foobar")
# r is the result from the database
#if python3
return r # or returnValue(r)
# if python2
# returnValue(r)
# every time you call a function that is wrapped with inlineCallbacks
# the return value of that function is Deferred
d = get_id('messages', 'message', 'Foo')
d.addCallback(lambda r: print("Result: %r" % (r, )))
reactor.run()