问题
如何在tornado的coroutine中调用同步阻塞的函数
解决方案
使用python内置标准库的concurrent.futures.ThreadPoolExecutor
和tornado.concurrent.run_on_executor
解决示例
a.使用concurrent.futures.ThreadPoolExecutor
#-*-coding:utf-8-*-
import time
from tornado.gen import coroutine
from tornado.ioloop import IOLoop
from concurrent.futures import ThreadPoolExecutor
def func():
time.sleep(2)
print(10)
def foo():
time.sleep(1)
print(15)
@coroutine
def main():
pool = ThreadPoolExecutor(2)
@coroutine
def sync_func1():
yield pool.submit(func,)
@coroutine
def sync_func2():
yield pool.submit(foo,)
t1 = time.time()
yield [sync_func1(), sync_func2()]
print(time.time() - t1)
if __name__ == '__main__':
IOLoop.current().run_sync(main)
b.使用run_on_executor
#-*-coding:utf-8-*-
import os.path
import time
from tornado.gen import coroutine
from tornado.ioloop import IOLoop
from tornado.concurrent import run_on_executor
from concurrent.futures import ThreadPoolExecutor
class My(object):
def __init__(self):
self.executor = ThreadPoolExecutor(3)
@run_on_executor
def f(self):
print(os.path.join(os.path.dirname(__file__), 'python'))
time.sleep(2)
print(10)
@run_on_executor
def f1(self):
time.sleep(1)
print(15)
@run_on_executor
def f2(self):
time.sleep(1.5)
print('hello, world!')
@coroutine
def main():
m = My()
t1 = time.time()
yield [m.f1(), m.f2(), m.f()]
print(time.time() - t1)
if __name__ == '__main__':
IOLoop.current().run_sync(main)
总结
我们直接运行上面的两个同步的函数,耗时需要3秒。但我们利用了ThreadPoolExecutor
之后,总耗时只需要2秒左右。下面是运行结果: