async/await套路编程
对于并发任务,通常是用生成消费模型,对队列的处理可以使用类似master-worker的方式,master主要用户获取队列的msg,worker用户处理消息。
为了简单起见,并且协程更适合单线程的方式,我们的主线程用来监听队列,子线程用于处理队列。这里使用redis的队列。主线程中有一个是无限循环,用户消费队列。
也即:
在主线程里,一个无限循环,一个不断加入的新任务协程:
一个loop.run_forever(),一个async def do_sleep2(x, queue, msg=""):
子线程作消费者。(代码里没有演示,只是用子线程有循环事件和异步加入协程,主线程循环结果)
import time
import asyncio
from queue import Queue
from threading import Thread
from asyncio.futures import Future
from collections.abc import Coroutine, Generator
"""
只要在一个生成器函数头部用上 @asyncio.coroutine 装饰器
就能将这个函数对象,【标记】为协程对象。注意这里是【标记】,划重点。
实际上,它的本质还是一个生成器。
标记后,它实际上已经可以当成协程使用。
"""
@asyncio.coroutine
def hello2():
yield from asyncio.sleep(1)
coroutine2 = hello2()
print(isinstance(coroutine2, Generator))
print(isinstance(coroutine2, Coroutine))
# True
# False
"""
只要在一个函数前面加上 async 关键字,这个函数对象是一个协程,
通过isinstance函数,它确实是Coroutine类型。
"""
async def hello(name):
print("Hello, ", name)
time.sleep(2)
return 'stop 2 seconds.'
# 定义协程对象
coroutine = hello("world")
print(isinstance(coroutine, Coroutine))
# True
# 定义事件循环对象容器
loop = asyncio.get_event_loop()
# 将协程转为task任务
# task = asyncio.ensure_future(coroutine)
task = loop.create_task(coroutine)
print(isinstance(task, Future))
# True
# 将task任务扔进事件循环对象中并触发
loop.run_until_complete(task)
# task.result() 可以取得返回结果
print('return value: {}'.format(task.result()))
# Hello, world
# return value: stop 2 seconds.
# 协程函数
async def do_some_work(x):
print('waiting: ', x)
await asyncio.sleep(x)
return 'Done after {}s'.format(x)
# 协程对象
coroutine1 = do_some_work(1)
coroutine2 = do_some_work(2)
coroutine4 = do_some_work(4)
# 将协程转成task,并组成list
tasks = [
asyncio.ensure_future(coroutine1),
asyncio.ensure_future(coroutine2),
asyncio.ensure_future(coroutine4),
]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
# loop.run_until_complete(asyncio.gather(*tasks))
for task in tasks:
print('Task ret: ', task.result())
# waiting: 1
# waiting: 2
# waiting: 4
# Task ret: Done after 1s
# Task ret: Done after 2s
# Task ret: Done after 4s
# 外部的协程函数
async def main():
coroutine1 = do_some_work(1)
coroutine2 = do_some_work(2)
coroutine4 = do_some_work(4)
tasks = [
asyncio.ensure_future(coroutine1),
asyncio.ensure_future(coroutine2),
asyncio.ensure_future(coroutine4),
]
# 【重点】:await 一个task列表(协程)
# dones:表示已经完成的任务
# pendings:表示未完成的任务
dones, pendings = await asyncio.wait(tasks)
for task in dones:
print('Task ret: ', task.result())
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
# waiting: 1
# waiting: 2
# waiting: 4
# Task ret: Done after 1s
# Task ret: Done after 2s
# Task ret: Done after 4s
"""
协程中的状态
Pending:悬而未决的状态
Running:事件循环正在调用执行任务
Done:任务执行完毕
Cancelled:Task被取消后的状态
asyncio.wait:接收形式少点,控制性强,手工循环结果。
asyncio.gather:接收形式广泛,直接返回结果。
"""
def start_loop(loop):
# 一个在后台永远运行的事件循环
asyncio.set_event_loop(loop)
loop.run_forever()
def start_loop2(loop):
# 一个在后台永远运行的事件循环
asyncio.set_event_loop(loop)
loop.run_forever()
def do_sleep(x, queue, msg=""):
time.sleep(x)
queue.put(msg)
async def do_sleep2(x, queue, msg=""):
await asyncio.sleep(x)
queue.put(msg)
queue = Queue()
queue2 = Queue()
new_loop = asyncio.new_event_loop()
new_loop2 = asyncio.new_event_loop()
t = Thread(target=start_loop, args=(new_loop, ))
t.start()
t2 = Thread(target=start_loop2, args=(new_loop2, ))
t2.start()
print(time.ctime())
# 动态添加两个协程
# 这种方法,在主线程是同步的
new_loop.call_soon_threadsafe(do_sleep, 6, queue, "第一个")
new_loop.call_soon_threadsafe(do_sleep, 6, queue, "第二个")
# 动态添加两个协程
# 这种方法,在主线程是异步的
asyncio.run_coroutine_threadsafe(do_sleep2(6, queue, "第1个"), new_loop2)
asyncio.run_coroutine_threadsafe(do_sleep2(6, queue, "第2个"), new_loop2)
while True:
msg = queue.get()
print("{} 协程运行完成。。。".format(msg))
print(time.ctime())
# Thu Dec 27 19:51:00 2018
# 第一个 协程运行完成。。。
# Thu Dec 27 19:51:06 2018
# 第二个 协程运行完成。。。
# Thu Dec 27 19:51:12 2018
while True:
msg = queue2.get()
print("{} 协程运行完成。。。".format(msg))
print(time.ctime())
# 第1个 协程运行完成。。。
# Thu Dec 27 20:02:10 2018
# 第2个 协程运行完成。。。
# Thu Dec 27 20:02:10 2018
async/await套路编程的更多相关文章
- 【转】C# Async/Await 异步编程中的最佳做法
Async/Await 异步编程中的最佳做法 Stephen Cleary 近日来,涌现了许多关于 Microsoft .NET Framework 4.5 中新增了对 async 和 await 支 ...
- 【转】以Python为例的Async / Await的编程基础
转, 原文:https://www.cnblogs.com/middleware/p/11996731.html 以Python为例的Async / Await的编程基础 -------------- ...
- .NET Web应用中为什么要使用async/await异步编程
前言 什么是async/await? await和async是.NET Framework4.5框架.C#5.0语法里面出现的技术,目的是用于简化异步编程模型. async和await的关系? asy ...
- C#中 Thread,Task,Async/Await 异步编程
什么是异步 同步和异步主要用于修饰方法.当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法:当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务,调 ...
- async/await 异步编程(转载)
转载地址:http://www.cnblogs.com/teroy/p/4015461.html 前言 最近在学习Web Api框架的时候接触到了async/await,这个特性是.NET 4.5引入 ...
- async/await 异步编程
前言 最近在学习Web Api框架的时候接触到了async/await,这个特性是.NET 4.5引入的,由于之前对于异步编程不是很了解,所以花费了一些时间学习一下相关的知识,并整理成这篇博客,如果在 ...
- c# 关于async/await异步编程的浅析和使用
线程的同步运行,时效性慢,异步运行,时效性快! 在c#5.0引出了async/await关键字,可以用其来进行异步编程. async/await定义异步方法的语法如下: 1.在方法的返回类型前面加上a ...
- .NET 中的 async/await 异步编程
原文出处: Teroy 的博客 前言 最近在学习Web Api框架的时候接触到了async/await,这个特性是.NET 4.5引入的,由于之前对于异步编程不是很了解,所以花费了一些时间学习一下相关 ...
- 以Python为例的Async / Await的编程基础
来源:Redislabs 作者:Loris Cro 翻译:Kevin (公众号:中间件小哥) 近年来,许多编程语言都在努力改进它们的并发原语.Go 语言有 goroutines,Ruby 有 fibe ...
随机推荐
- PL/SQL可以连oracle,但是jdbc连不上 【转】
场景描述 此处是jdbc连接: try { Class.forName("oracle.jdbc.driver.OracleDriver"); String url = " ...
- Bugly实现app全量更新
转 http://blog.csdn.net/qq_33689414/article/details/54911895Bugly实现app全量更新 Bugly官网文档 一.参数配置 在app下的gra ...
- 一、GPIO操作
1.1 硬件原理图 四个引脚接到LED上,跟别是GPF4,GPF5,GPF6和GPF7,前三个引脚分别控制三个LED,GPF7此引脚作为DM9000网卡的中断. 发光二极管的正极接3.3V电源,负极接 ...
- linux4.10.8 内核移植(一)---环境搭建及适配单板。
一.环境搭建 源码包下载:git clone https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.10.8.tar.gz 或者直接去kernel. ...
- SQL——将表中的最大ID+1插入新的ID中------Insert into 表 MAX(表id) +1
表结构:group表(groupid int,groupname varchar) 表中数据:id name 分组1 分组2 分组3 分组4 ----------------------------- ...
- 第14月第30天 svn 撤销ignore revert
1. 直接到被ignore的位置,执行: svn add <你被ignore的文件名> --no-ignore –no-ignore是取消忽略 如果是add目录,你可以: svn add ...
- logback配置按天产生日志文件
1 依赖Jar包 pom配置 也可以根据自己的版本来 <dependency> <groupId>org.slf4j</groupId> <artifactI ...
- Linux的记事本 Vi和Vim
⒈Vi和Vim的三种模式 ①正常模式 在正常模式下可以使用快捷键 默认进入的是正常模式 ②编辑模式(插入模式) 在该模式下可以输入内容 按下I,i,O,o,A,a,R,r等任何一个字母之后才可以进入该 ...
- caffe-win10-cifar10另
上一篇主要以bat形式实现了leveldb形式的cifar10,因为对于shell脚本不甚熟悉,所以这次专门利用.sh调用来实现lmdb形式的cifar10. 1.下载数据 同上一篇. 2.数据转换和 ...
- Django 聚合与查询集API实现侧边栏
本文从Django官方文档总结而来,将聚合的主要用法和查询集的常见方法做一归纳. 聚合 1. 聚合的产生来源于django数据库查询,通常我们使用django查询来完成增删查改,但是有时候需要更复杂的 ...