Python-tornado 中一段关于 gen 模块的使用, 其逻辑如何理解?

发布于 2022-09-04 02:37:37 字数 1059 浏览 13 评论 0

问题

如同自己当初理解回调一样, ( 一旦回调层次多了, 就感觉理解起来有点难度 )

详细问题已经在代码中注明, 见相关代码

相关代码

from tornado import gen
from tornado.ioloop import IOLoop
from tornado.queues import Queue

q = Queue(maxsize=2)

@gen.coroutine
def consumer():
    while True:
        item = yield q.get()
        try:
            print('Doing work on %s' % item)
            yield gen.sleep(0.01)
        finally:
            q.task_done()

@gen.coroutine
def producer():
    for item in range(5):
        yield q.put(item)
        print('Put %s' % item)

@gen.coroutine
def main():
    # Start consumer without waiting (since it never finishes).
    IOLoop.current().spawn_callback(consumer)
    yield producer()     # Wait for producer to put all tasks.
    yield q.join()       # Wait for consumer to finish all tasks.
    print('Done')

IOLoop.current().run_sync(main)

如上代码, 初看, 能懂它的大概意思, 但是具体一行一行看下来, 它的执行顺序就不是很清楚了, 下面是我的一些理解
1. 进入 main
2. consumer 派生一个回调, 在那里等待
3. producer 协程, 不断进入又出来( 我所理解的协程: 不断进入, 不断出来 )
4. q.join 协程, 卡住

以上理解, 有何错误的地方?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

岁月静好 2022-09-11 02:37:37

yield 是让出时间片的意思。yield producer() 就是把时间交给 producer(),所以它自己是处于等待状态。

这里并没有(显式的)回调。

协程即「协作式多线程」,一个线程主动让出时间片给另外的线程。yield 一次,当然只让出一次。

main 这个协程会先在 yield producer() 处等待。五个任务生产完毕之后,它才会接着到 yield q.join() 这里等待任务处理完毕。

秋日私语 2022-09-11 02:37:37
from tornado import gen
from tornado.ioloop import IOLoop
from tornado.queues import Queue

q = Queue(maxsize=2)

@gen.coroutine
def consumer():
    while True:
        item = yield q.get() # 等待获取到q里面的值,如果生产者没有生产,会一直等待。
        try:
            print('Doing work on %s' % item)
            yield gen.sleep(0.01)
        finally:
            q.task_done() # 标记任务完成,如果不标记,那么
                          # q.join() 会从q.queue size() == 0 一直阻塞到timeout

@gen.coroutine
def producer():
    for item in range(5):
        yield q.put(item) # 等待插入对象成功,因为队列长度为2,
                          # 所以,消费者没能及时q.get(),这里就会阻塞
        print('Put %s' % item)

@gen.coroutine
def main():
    # Start consumer without waiting (since it never finishes).
    IOLoop.current().spawn_callback(consumer) # 调用consumer,这里不用等结果,算是异步了,
                                              # 不报错的情况下跟直接用 consumer()差不多
    yield producer()     # 等待producer执行完成——put完所有5个值.这时按理说,q里面有2个对象
    yield q.join(timeout=5)       # 等待q里面的所有对象都被task_done().如果这里不 yield 等待,
                         # 那么producer完成后,程序就退出了,consumer 没有完全消费完
    print('Done')

IOLoop.current().run_sync(main) #运行main函数,main执行完自动结束,不用调用close()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文