版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/happyAnger6/article/details/51291221
几种常用的协程方式:

1.回调函数

如果你要执行的异步代码是基于回调函数而不是基于Future的,你可以将异步代码通过Task装饰起来。这样Task装饰器会为你添加callback并返回一个Future,这样你就可以用yield来执行异步代码。

@gen.coroutine
def call_task():
# Note that there are no parens on some_function.
# This will be translated by Task into
# some_function(other_args, callback=callback)
  yield gen.Task(some_function, other_args)
在some_function里,你可以执行基于回调函数的异步代码。gen.Task会为你设置好一个callback并通过callback参数传递给some_function,你在some_function内部将callback传递给异步代码所需的callback即可。

2.调用阻塞函数

调用阻塞函数最简单的办法是通过使用ThreadPoolExecutor,它会返回一个Future.

thread_pool = ThreadPoolExecutor(4)

@gen.coroutine
def call_blocking():
  yield thread_pool.submit(blocking_func, args)

3.并行

coroutine装饰器能够识别Future的列表或字典,能够并行执行它们并等待全部完成。

@gen.coroutine
def parallel_fetch(url1, url2):
  resp1, resp2 = yield [http_client.fetch(url1),
  http_client.fetch(url2)]

@gen.coroutine
def parallel_fetch_many(urls):
  responses = yield [http_client.fetch(url) for url in urls]
  # responses is a list of HTTPResponses in the same order

@gen.coroutine
def parallel_fetch_dict(urls):
  responses = yield {url: http_client.fetch(url) for url in urls}
  # responses is a dict {url: HTTPResponse}

4.在yield前插入其它代码

有时候,你需要暂存一个Future而不立即yield它。在此之前可以执行一些其它操作。

@gen.coroutine
def get(self):
  fetch_future = self.fetch_next_chunk()
  while True:
    chunk = yield fetch_future #这里对取到的Future执行yield
    if chunk is None: break
    self.write(chunk)
    fetch_future = self.fetch_next_chunk() #先得到Future而不立刻对其yield
    yield self.flush()

5.循环

由于在python没有办法对for和while循环的每次迭代yield并同时获取结果,所以在循环中使用协程需要一些技巧。

你需要将循环条件和访问结果分开进行,下面的例子演示了这一点:

motor是一个mongodb的python api,它的实现也是基于协程方式,可以十分方便地在tornado中使用它。

import motor
db = motor.MotorClient().test

@gen.coroutine
def loop_example(collection):
  cursor = db.collection.find()
  while (yield cursor.fetch_next):
    doc = cursor.next_object()

6.在后台执行

PeriodicCallback(用于定期地执行一个函数)在协程中并不十分常用。你可以在协程中使用一个循环,在循环中使用tornado.gen.sleep达到同样的效果。

@gen.coroutine

def minute_loop():
  while True:
    yield do_something()
    yield gen.sleep(60)

# Coroutines that loop forever are generally started with
# spawn_callback().
IOLoop.current().spawn_callback(minute_loop)
有时候,你可能需要执行一个更复杂的循环逻辑。比如,上面的例子中循环体每60+N s运行一次,N是do_something()函数执行的时间.如果你想精确控制每次循环执行时间为60s,你可以像下面这样做:

@gen.coroutine
def minute_loop2():
  while True:
    nxt = gen.sleep(60) # 启动一个定时器并不yield它.
    yield do_something() # 在执行定时器的同时执行函数
    yield nxt # 此时再等待定时器超时.

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

tornado用户指引(四)------tornado协程使用和原理(三)的更多相关文章

  1. tornado用户指引(二)------------tornado协程实现原理和使用(一)

    摘要:Tornado建议使用协程来实现异步调用.协程使用python的yield关键字来继续或者暂停执行,而不用编写大量的callback函数来实现.(在linux基于epoll的异步调用中,我们需要 ...

  2. tornado用户指引(三)------tornado协程使用和原理(二)

    Python3.5  async和await async和await是python3.5引入的2个新的关键字(用这两个关键字编写的函数也称之为"原生协程"). 从tornado4. ...

  3. python并发编程之进程、线程、协程的调度原理(六)

    进程.线程和协程的调度和运行原理总结. 系列文章 python并发编程之threading线程(一) python并发编程之multiprocessing进程(二) python并发编程之asynci ...

  4. GO GMP协程调度实现原理 5w字长文史上最全

    1 Runtime简介 Go语言是互联网时代的C,因为其语法简洁易学,对高并发拥有语言级别的亲和性.而且不同于虚拟机的方案.Go通过在编译时嵌入平台相关的系统指令可直接编译为对应平台的机器码,同时嵌入 ...

  5. 深入浅出!从语义角度分析隐藏在Unity协程背后的原理

    Unity的协程使用起来比较方便,但是由于其封装和隐藏了太多细节,使其看起来比较神秘.比如协程是否是真正的异步执行?协程与线程到底是什么关系?本文将从语义角度来分析隐藏在协程背后的原理,并使用C++来 ...

  6. Golang源码探索(二) 协程的实现原理

    Golang最大的特色可以说是协程(goroutine)了, 协程让本来很复杂的异步编程变得简单, 让程序员不再需要面对回调地狱, 虽然现在引入了协程的语言越来越多, 但go中的协程仍然是实现的是最彻 ...

  7. Golang源码探索(二) 协程的实现原理(转)

    Golang最大的特色可以说是协程(goroutine)了, 协程让本来很复杂的异步编程变得简单, 让程序员不再需要面对回调地狱,虽然现在引入了协程的语言越来越多, 但go中的协程仍然是实现的是最彻底 ...

  8. 协程概念,原理及实现(c++和node.js实现)

    协程 什么是协程 wikipedia 的定义: 协程是一个无优先级的子程序调度组件,允许子程序在特点的地方挂起恢复. 线程包含于进程,协程包含于线程.只要内存足够,一个线程中可以有任意多个协程,但某一 ...

  9. tornado 协程的实现原理个人理解;

    tornado实现协程的原理主要是利用了(1)python里面的generator (2)future类和ioloop相互配合,两者之间的相互配合是通过gen.coroutine装饰器来实现的: 具体 ...

随机推荐

  1. Sqlite 数据库分页查询(ListView分页显示数据)

    下面介绍一下我的这个demo. 流程简述: 我在raw文件夹下面放了名称为city的数据库,里面包含全国2330个城市,以及所属省,拼音简写等信息. 首先 在进入MainActivity的时候,创建数 ...

  2. WPF控件相对位置解析

    WPF控件相对位置的获取方法是比较简单的.对于初学者来说,掌握这一技巧的应用,可以帮助以后对WPF的深入学习,而且在实际使用中,这是一个非常常用的方法. 我们知道WPF有着比较灵活的布局方式,关于某个 ...

  3. MVC中重定向几种方法

    //1.Response.Redirect using System; using System.Collections.Generic; using System.Linq; using Syste ...

  4. July 25th 2017 Week 30th Tuesday

    Everything is always more beautiful reflected in your eyes. 一切事物映在你的眼里都会变得更美. Looking in your eyes, ...

  5. ZT Factory Pattern

    图中的虚线箭头表示依赖关系

  6. MongoDB插入文档

    db.collection.insertOne() 插入单个文档.db.collection.insertMany() 插入多个文档.db.collection.insert() 插入单/多个文档.  ...

  7. 不规矩的xml与JAVA对象互相转换的小技巧-使用Marshaller

    摘要:将XML文档与JAVA对象互转是很常见的需求,如果XML定义很规整这很好实现.然而在现实中“不规矩”的XML可能更常见,Marshaller便无能为力了吗?下面是一个小技巧,调整一下思维便能重用 ...

  8. 使用Vue-cli脚手架

    使用vue-cli脚手架开发vue项目,有以下好处: (1)成熟的Vue项目架构设计. (2)本地测试服务器(热更新). (3)集成打包上线方案. Vue-cli系统要求: Node.js(>= ...

  9. django 静态文件

    django 1.8版本以上 django 静态文件配置. 小作之前, 一直觉得django的静态文件配置非常的麻烦. 1. 要设置url(r'^static/(?P<path>.*)&a ...

  10. node express 跨域问题

    express = require('express'); var app = express(); //设置跨域访问 app.all('*', function(req, res, next) { ...