版权声明:本文为博主原创文章,未经博主允许不得转载。 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. SpringBoot开发(改变环境属性、读取资源文件、Bean 配置、模版渲染、profile 配置)

    1.概念 SpringBoot 开发深入 2.具体内容 在之前已经基本上了解了整个 SpringBoot 运行机制,但是也需要清楚的认识到以下的问题,在实际的项目开发之中,尤其是 Java 的 MVC ...

  2. 基于Vue的WebApp项目开发(一)

    了解webpack的魔力: 项目结构以及开发环境 webpack初体验之打包文件 1.首先创建三个文件,分别是index.html.main.js和calc.js index.html <!DO ...

  3. Linux 下载百度网盘大文件

    Linux 下没有百度网盘客户端,用浏览器下载速度慢得急死人 鼠标移到链接处, 右键, 然后复制链接 接着在终端里输入 axel -n 50 -o filename.ext “粘贴链接到此处” axe ...

  4. 阿里云安装jdk报错gzip: stdin: unexpected end of file

    在阿里云上面安装jdk时候报了这个问题,如下图所示 然后看了下jdk应该是有150多M的,但是阿里云上面的只有1M多,删除 重新下载... tar zxvf jdk 好了

  5. 如何为运行的 ARM Linux 启用 LAD2.3 版本的诊断扩展

    Linux Azure Diagnostic (LAD) 扩展现在已经发布了 3.0 版本,但在 Azure 中国区,目前可用的最新版本还是 2.3. 虽然 Azure 门户提供了简单的操作版本为 L ...

  6. SQL Server ->> FileTable

    FileTable是SQL Server 2012的新特性之一.它是基于SQL Server 2008的FILESTREAM特性上而来的,允许我们把Windows文件存储在SQL Server中,让S ...

  7. Linux ->> Ubuntu 14.04 LTE下安装JDK 1.8

    先到Oracle官网的下载中心下载JDK8的tar包到本地. 下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-dow ...

  8. tcp-full.cc

    ns2--tcp-full.cc /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */ /* * Copy ...

  9. Hyper-V迁移---委派

    在Hyper-V管理器中-实时迁移,选择“使用kerberos",如图1所示 在AD中,找到Hyper-V宿主,分别设置委派,如图2所示    图1               图2

  10. skype for business server2015部署向导启动服务失败

    命令行执行start-cspool失败 解决: 1.cmd执行servers.msc打开服务列表,将所有skype服务启动,默认是延迟启动 2.用管理员权限打开cmd,而不是普通权限 重新执行启动服务 ...