gpt4 book ai didi

python - 使用 Tornado 和 pyodbc 进行异步调用

转载 作者:太空宇宙 更新时间:2023-11-04 06:38:23 26 4
gpt4 key购买 nike

我想实现一个基于tornado的web服务,为用户提供数据库查询服务。我使用 pyodbc 模块连接到数据库并进行查询。在实践中,我发现打印查询结果会花费很长时间。也就是说如果我用下面的代码打印查询结果

while 1:
data = cursor.fetchone()
if not data: break
self.write(data + '\n')
self.flush()

sql命令是这样的

select * from <a large dummy table>

在循环结束之前,tornado 不会打印查询结果。而且需要很长时间。

我想利用 tornado 的非阻塞异步特性,即使打印当前用户查询请求的循环尚未完成,其他用户也可以使用该 web 服务。

所以我这样写:

@tornado.web.asynchronous
def get(self):
try:
cnxn = pyodbc.connect(self.server, self.driver, self.table, self.uid, self.pwd)
except Exception, e:
print e
return

try:
self.cur = cnxn.execute(self.sql)
except Exception, e:
print e
return

self.wait_for_query(callback=self.async_callback(self.on_finish))

def wait_for_query(self, callback):
while 1:
data = self.cur.fetchone()
if not data: break
self.write(data)
self.flush()
callback()

def on_finish(self):
self.finish()

我读了这篇文章: Asynchronous COMET query with Tornado and Prototype并且知道我的解决方案行不通。但我当然不能使用 add_timeout,因为我无法确定迭代会持续多长时间。那么我怎样才能通过这个来实现我的目标呢?

最佳答案

为了允许单线程 Tornado 服务器在这样的请求中异步,您必须将控制权交还给 I/O 循环。试试这个:

class LongRequestHandler(tornado.web.RequestHandler):
def database_callback(self):
data = self.cur.fetchone()
if not data:
self.finish()
self.cnxn.close()
else:
self.write(data)
self.flush()
tornado.ioloop.IOLoop.instance().add_callback(self.database_callback)

@tornado.web.asynchronous
def get(self):
try:
self.cnxn = pyodbc.connect(self.server, self.driver, self.table, self.uid, self.pwd)
except Exception, e:
print e
return

try:
self.cur = self.cnxn.execute(self.sql)
except Exception, e:
print e
return

tornado.ioloop.IOLoop.instance().add_callback(self.database_callback)

但是,值得注意的是,每个数据库提供商都不同。据我了解,对于 MySQL,大部分时间/处理实际上将花在 execute() 调用上,而不是循环遍历数据,因为 MySQL 处理整个查询并返回完整的结果集。如果您正在使用执行相同操作的数据库提供程序,您可能需要在位于 Tornado 后面的工作进程中处理这样的请求。

编辑 我的例子只是一个例子。实际上,您可能想要测试您的回调并可能在返回之前循环通过相当多的行,否则您会浪费大量 CPU 时间在 IO 循环上的函数之间切换,而不是实际处理请求。在做了一些测试之后,我担心的关于 MySQL 的事情是真的 - 执行/查询语句本身是导致锁定的原因,所以这个解决方案在那种情况下真的无济于事。

关于python - 使用 Tornado 和 pyodbc 进行异步调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5183541/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com