首页 > 能解释一下tornado.gen.coroutine代码中的这段注释吗?

能解释一下tornado.gen.coroutine代码中的这段注释吗?

    .. warning::

       When exceptions occur inside a coroutine, the exception
       information will be stored in the `.Future` object. You must
       examine the result of the `.Future` object, or the exception
       may go unnoticed by your code. This means yielding the function
       if called from another coroutine, using something like
       `.IOLoop.run_sync` for top-level calls, or passing the `.Future`
       to `.IOLoop.add_future`.

对于This means yielding the function if called from another coroutine这句意思不是很懂。


首先,你要理解什么是coroutine, 一般认为(xx)routine是一个轻量级的线程,比如golang是goroutine,有些更小众的语言甚至直接叫process比如erlang,但这里的进程、轻量级线程都是派生于操作系统之上的,也就是位于pthread之上的一个抽象概念。
有的操作系统提供这种原生的支持,比如windows的fiber,线程和他们的重要区别是前者的调度和切换由操作系统代为进行,后者需要调用者或者是语言设计者自己去切换或管理,具体的实现的时候,稍微有点差别,但大体意思一致。
见这里
https://www.zhihu.com/question/21483863

Python也能模仿着实现自己的routine,也就是coroutine,主要通过python的yield来实现。传送,见这里
http://blog.csdn.net/xiaobing_blog/artic...

见下面的代码

from tornado import gen
from tornado.ioloop import IOLoop

@gen.coroutine
def myRoutine():
    raise Exception("Exception")
    return 'hello'


@gen.coroutine
def test():
    print "here 1"
    r = myRoutine() # 这里有异常,但是不会触发test()异常,这里r是一个Future类型,代码仍会继续执行
    print "here 2" #正常输出


test()

IOLoop.instance().start()

原文中的意思是从一个coroutine里调用另外一个coroutine,如果没有用yield的方法的话,是抓不到最下面的那个myRoutine的异常的,如果myRoutine要检查是否有异常的话,必须使用下面的2种方式之一:
1) yield的方式

@gen.coroutine
def myRoutine():
    raise Exception("Exception")
    return 'hello'


@gen.coroutine
def test():
    print "here 1"
    res = yield gen.Task(myRoutine) 
    print "here 2" #不会执行

test()

IOLoop.instance().start()

2) 最外面使用run_sync包装,见下面

from tornado import gen
from tornado.ioloop import IOLoop

@gen.coroutine
def myRoutine():
    raise Exception("Exception")
    return 'hello'


@gen.coroutine
def test():
    print "here 1"
    myRoutine()
    print "here 2"


IOLoop.instance().run_sync(test)

原文的意思是鼓励程序员应该尽可能的处理异常,而非silent pass,所以提倡用yield的方案或run_sync,以便在coroutine之间调用的时候出现异常不能处理的情况
【热门文章】
【热门文章】