如何在tornado中以异步的方式调用同步函数

摘要:
')@coroutinedefmain():m=My()t1=time.time()yield[m.f1(),m.f2(),m.f()]printif__name__=='__main__':IOLoop.current()。run_Sync总结说,我们直接运行上述两个同步函数,这需要3秒钟。但是,在使用ThreadPoolExecutor之后,它只需要大约2秒。

问题
如何在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秒左右。下面是运行结果:

---------------------
作者:Easy_to_python
来源:CSDN
原文:https://blog.csdn.net/hjhmpl123/article/details/53673108
版权声明:本文为博主原创文章,转载请附上博文链接!

免责声明:文章转载自《如何在tornado中以异步的方式调用同步函数》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Eclipse控制台输出中文乱码问题的解决《关于长沙.NET技术社区未来发展规划》问卷调查结果公布下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

linux处理僵尸进程

由来 在linux下,如果一个进程终止,内核会释放该进程使用的所有存储区,关闭所有文件句柄等,但是,内核会为每个终止子进程保留一定量的信息。这些信息至少包括进程ID,进程的终止状态,以及该进程使用的CPU时间。当终止子进程的父进程调用wait或waitpid时就可以得到这些信息 僵尸进程指:一个进程退出后,而其父进程并没有为它收尸(调用wait或waitp...

详解 JS 中 new 调用函数原理

JavaScript 中经常使用构造函数创建对象(通过 new 操作符调用一个函数),那在使用 new 调用一个函数的时候到底发生了什么?先看几个例子,再解释背后发生了什么。 1)看三个例子 1.1 无 return 语句 构造函数最后没有 return 语句,这也是使用构造函数时默认情况,最后会返回一个新对象,如下: function Foo(age)...

Delphi中的线程类

文章来源: http://liukun966123.my.gsdn.net/2004/10/22/4797/ Delphi中的线程类 转贴于 华夏黑客同盟 http://www.77169.org Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书藉都有说到,但基本上都是对 TThread类的几个成员作一简单介绍,再...

C++异常

一、什么是异常处理         一句话:异常处理就是处理程序中的错误。 二、为什么需要异常处理,以及异常处理的基本思想         C++之父Bjarne Stroustrup在《The C++ Programming Language》中讲到:一个库的作者可以检测出发生了运行时错误,但一般不知道怎样去处理它们(因为和用户具体的应用有关);另一...

C++之匿名对象解析

我们知道在C++的创建对象是一个费时,费空间的一个操作。有些固然是必不可少,但还有一些对象却在我们不知道的情况下被创建了。通常以下三种情况会产生临时对象: 1,以值的方式给函数传参; 2,类型转换; 3,函数需要返回一个对象时; 现在我们依次看这三种情况: 一,以值的方式给函数传参。 我们知道给函数传参有两种方式。1,按值传递;2,按引用传递。按值传递时,...

[Python自学] Flask框架 (3) (路由、CBV、自定义正则动态路由、请求处理流程、蓝图)

一、路由系统 1.浅析@app.route的源码 我们使用@app.route("/index")可以给视图函数加上路由映射。我们分析一下@app.route装饰器的实现源码: def route(self, rule, **options): def decorator(f): endpoint = options.pop("en...