V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
mengzhuo
V2EX  ›  Python

求解Tornado gen.coroutine同步变异步的方法

  •  
  •   mengzhuo · 2013-12-30 14:10:01 +08:00 · 7134 次点击
    这是一个创建于 3981 天前的主题,其中的信息可能已经有所发展或是发生改变。
    跟着gen.coroutine走了N遍,源码也看过N遍了,yield generator实现coroutine的原理也了解,js callback也明白,但是问题是……



    中,用官方的asyncHTTPclient可以实现异步加载,但,比如在sleep_bug里面加上了time.sleep(1)就整个线程阻塞了。

    看网上的资料都说要改写function,添加上callback才能完成异步模式
    可是PEP 3148(http://www.python.org/dev/peps/pep-3148/)里的例子没有一个是这种模式的,都有executor来完成,可tornado中没有,不知道怎么改gen.coroutine成异步了
    11 条回复    2015-04-29 23:07:27 +08:00
    est
        1
    est  
       2013-12-30 15:25:29 +08:00
    看文档 `IOLoop.add_timeout` is a non-blocking alternative to `time.sleep
    mengzhuo
        2
    mengzhuo  
    OP
       2013-12-30 16:45:26 +08:00
    @est 那怎么理解gen.coroutine -> Runner模式呢?

    callback直接send给generator不就好了吗?
    zenliver
        3
    zenliver  
       2013-12-31 14:26:28 +08:00
    这里的异步是指io异步, time.sleep()会导致线程sleep, 当然会阻塞线程了, 正如@est所说, tornado有提供这样的功能, 如果你遇到cpu bound问题, 可以用tornado.concurrent.run_on_executor, backend用线程池还是进程池,还是其它什么, 看你想怎么实现了,,,如果仅仅只是想把一个同步的程序变为异步,,,这么做没什么好处,,,,纯粹闲的蛋痛。。。。
    mengzhuo
        4
    mengzhuo  
    OP
       2013-12-31 15:37:35 +08:00
    @zenliver
    不算是闲得慌
    关键是js的callback/信号模式还能理解,写点小程序神马的都没问题,到Tornado上就傻眼了,future只是yield出来,后面又可以像同步的方法调用,但实际上又是异步的 OTZ
    zenliver
        5
    zenliver  
       2013-12-31 15:58:54 +08:00
    你看看Runner的实现,,,一切就明白了
    b1074549
        6
    b1074549  
       2014-02-13 11:10:46 +08:00
    ThreadedResolver
    xunuoi
        7
    xunuoi  
       2015-03-09 11:51:34 +08:00
    用ThreadPoolExecutor来解决,举个例子:


    from tornado import gen,web
    from tornado.concurrent import run_on_executor
    #if in Python2, it need install by pip install futures
    from concurrent.futures import ThreadPoolExecutor

    from model.Movie import Movie

    class IndexHandler(web.RequestHandler):
    executor = ThreadPoolExecutor(2)
    @web.asynchronous
    @gen.coroutine
    def get(self): #用yield来返回一个迭代器函数
    mov = yield self.query_movie()
    self.write('llalalal')
    self.finish()

    @run_on_executor #此处是耗时的操作
    def query_movie(self):
    time.sleep(5)
    return 'sleep lallal'


    此时就是异步非阻塞的实现了(用线程解决的)
    mengzhuo
        8
    mengzhuo  
    OP
       2015-03-09 13:25:49 +08:00
    @xunuoi

    虽然我已经搞懂了……而且用epoll自己实现了一些异步功能
    但是还是谢谢回复哈
    fasling
        9
    fasling  
       2015-04-28 10:26:42 +08:00
    @xunuoi 我也是用了这种方法,但是想在on_finish的时候对query_movie的返回值做做一些别的事情,请问要怎么做?
    xunuoi
        10
    xunuoi  
       2015-04-29 15:45:13 +08:00
    @fasling 修饰器不行么?
    fasling
        11
    fasling  
       2015-04-29 23:07:27 +08:00
    @xunuoi 不知道怎么搞啊?求教
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2649 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 04:58 · PVG 12:58 · LAX 20:58 · JFK 23:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.