async 异步协程进阶
协程通过 async/await 语法进行声明,是编写异步应用的推荐方式
例如新定义一个协程(coroutine object):
async def foo():
return 42
首先先来介绍下:
认识aysn和asyncio都有哪些函数方法:
创建一个future 对象:
task = asyncio.create_task(foo())
或者使用
task=asyncio.ensure_future(foo())
那么如何判断创建的task到底是不是future 对象呢?
async def exetask():
# task = asyncio.create_task(foo())
task = asyncio.ensure_future(foo())
if isinstance(task,asyncio.Future):
print("yes")
else:
print("no")
s=await task
asyncio.run(exetask())
结果如下:
yes
答案是肯定的。 2.如何运行一个协程:
要真正运行一个协程,asyncio 提供了三种主要机制:
第一种:
asyncio.run()函数用来运行最高层级的入口点 "main()" 函数 (参见上面的示例。)
第二种:
通过loop对象实现:
loop=asyncio.get_event_loop()
async def jobs():
i=10
while i>0:
# time.sleep(0.5)
i=i-1
return 0
tasks=[asyncio.ensure_future(jobs(k)) for k in range(1,4)]
res=loop.run_until_complete(asyncio.gather(*tasks))
print(res)
loop.close()
3.并发
第1种并发运行:
当一个协程通过asyncio.create_task()等函数被打包为一个 任务,asyncio.create_task(coro)将 coro 协程 打包为一个Task排入日程准备执行,
返回 Task 对象。此函数 在 Python 3.7 中被加入。在 Python 3.7 之前,of course你也可以改用低层级的asyncio.ensure_future()函数, This works in all Python versions but is less readable
#### ordinal job async
async def jobs():
i=10
while i>0:
# time.sleep(0.5)
i=i-1
return 0
async def get_status():
r=await jobs()
return r
loop=event=asyncio.get_event_loop()
tasks = [asyncio.create_task(get_status()) for k in range(1,4)]
for task in tasks:
r=loop.run_until_complete(asyncio.wait_for(task,timeout=10))
print(r)
这里我采用了比较低级的loop事件对象来调用run_until_complete() 方法来实现:
事实上开发者一般更喜欢采用高级用法asyncio.wait()或者asyncio.wait_for()来实现这写异步任务调用:
在进行下面介绍之前我想你应该先了解:asyncio.wait_for(aw, timeout, *, loop=None)
等待 aw 可等待对象 完成,指定 timeout 秒数后超时。
如果 aw 是一个协程,它将自动作为任务加入日程。
timeout 可以为 None,也可以为 float 或 int 型数值表示的等待秒数。如果 timeout 为 None,则等待直到完成。
如果发生超时,任务将取消并引发 asyncio.TimeoutError.
函数将等待直到目标对象确实被取消,所以总等待时间可能超过 timeout 指定的秒数。
如果等待被取消,则 aw 指定的对象也会被取消。
loop 参数已弃用,计划在 Python 3.10 中移除。
asyncio.wait(aws, *, loop=None, timeout=None, return_when=ALL_COMPLETED)
并发运行 aws 指定的 可等待对象 并阻塞线程直到满足 return_when 指定的条件。
如果 aws 中的某个可等待对象为协程,它将自动作为任务加入日程。直接向 wait() 传入协程对象已弃用,因为这会导致 令人迷惑的行为。
返回两个 Task/Future 集合: (done, pending)。
用法:
done, pending = await asyncio.wait(aws)
loop 参数已弃用,计划在 Python 3.10 中移除。
如指定 timeout (float 或 int 类型) 则它将被用于控制返回之前等待的最长秒数。
请注意此函数不会引发 asyncio.TimeoutError。当超时发生时,未完成的 Future 或 Task 将在指定秒数后被返回。
return_when 指定此函数应在何时返回。它必须为以下常数之一:
|
常数 |
描述 |
|---|---|
|
|
函数将在任意可等待对象结束或取消时返回。 |
|
|
函数将在任意可等待对象因引发异常而结束时返回。当没有引发任何异常时它就相当于 |
|
|
函数将在所有可等待对象结束或取消时返回。 |
与 wait_for() 不同,wait() 在超时发生时不会取消可等待对象。
如何验证wait 不取消,wait_for 取消aw对象呢:
我们来看个例子:
先看wait_for:
async def foo(k=0):
await asyncio.sleep(30)
return k async def exetask():
task=asyncio.create_task(foo(k=1))
try:
await asyncio.wait_for(task,timeout=1)
print(task.cancelled())
#3.7 改为当 aw 因超时被取消,wait_for 会等待 aw 被取消,3.7之前直接报异常,
except asyncio.TimeoutError:
print("timeout ")
# task.cancel()
print(task.cancelled())
asyncio.run(exetask())
结果:
C:\Python37\python.exe D:/workspace/AutoFate/src/commonutils/asyncutils.py
timeout
True
再看wait,这里注意由于waitexpect a list of futures, not Task,我换种写法:
async def foo(k=0):
await asyncio.sleep(30)
return k async def exetask():
task = asyncio.create_task(foo(k=1))
try:
#请注意wait函数不会引发 asyncio.TimeoutError
await asyncio.wait([task], timeout=1)
## 3.7 改为当 aw 因超时被取消,wait_for 会等待 aw 被取消,3.7之前直接报异常,
# await asyncio.wait_for(task,timeout=1) except asyncio.TimeoutError:
print("timeout ")
print(task.cancelled()) asyncio.run(exetask())
结果:
C:\Python37\python.exe D:/workspace/AutoFate/src/commonutils/asyncutils.py
False
Process finished with exit code 0
这里完美的展现了阻塞的魅力!!!!!!!
第2种并发运行:
awaitableasyncio.gather(*aws, loop=None, return_exceptions=False)
并发 运行 aws 序列中的 可等待对象。
下面来看个简单的例子:
async def count(k):
print(f"start job{k} {time.asctime()} ")
await asyncio.sleep(0.6)
print(f"end job{k} {time.asctime()}")
return k
async def mayns():
r=await asyncio.gather(count(1),count(2))
return r
def test():
import time
st=time.perf_counter()
results=asyncio.run(mayns())
elapsed=time.perf_counter()-st
print(f"result return :{results} execute in {elapsed:0.2} seconds.")
运行结果:
start job1 Fri Dec 13 23:00:38 2019
start job2 Fri Dec 13 23:00:38 2019
end job1 Fri Dec 13 23:00:39 2019
end job2 Fri Dec 13 23:00:39 2019
result return :[1, 2] execute in 0.6 seconds.
gather直接返回的是调用的task的所有result列表
当然你也可以这样搜集任务:
最后介绍一下如何实现异步http请求:
# request 库同步阻塞,aiohttp才是异步的请求,pip install aiohttp
from aiohttp import ClientSession as session
async def test2(k):
r=await other_test(k)
return r
async def other_test(k):
print("start await job %s,%s"%(k,time.asctime()))
urls = ["http://127.0.0.1:8000/index", "http://127.0.0.1:8000/stuTable/"]
async with session() as request:
async with request.get(urls[0]) as rq:
r=await rq.read()
res=r.decode("utf-8")
print("end await job %s,%s"%(k,time.asctime()))
return res def test_aiohttp():
klist=[100,50,88]
loop=asyncio.get_event_loop()
tasks=[asyncio.ensure_future(test2(k)) for k in klist]
# loop.run_until_complete(asyncio.wait(tasks))
#可通过asyncio.gather(*tasks)将响应全部收集起来
res=loop.run_until_complete(asyncio.gather(*tasks))
print(res)
loop.close()
结果:
C:\Python37\python.exe D:/workspace/AutoFate/src/commonutils/asyncutils.py
start await job 100,Fri Dec 13 23:54:31 2019
start await job 50,Fri Dec 13 23:54:31 2019
start await job 88,Fri Dec 13 23:54:31 2019
end await job 88,Fri Dec 13 23:54:31 2019
end await job 50,Fri Dec 13 23:54:31 2019
end await job 100,Fri Dec 13 23:54:31 2019
['{"user": "test001", "msg": "this is test index view "}', '{"user": "test001", "msg": "this is test index view "}', '{"user": "test001", "msg": "this is test index view "}']
Process finished with exit code 0
服务是自己用djangO起的:
from django.shortcuts import render
# Create your views here.
from django.http import HttpResponse
import json
from . models import Student,Grade
from django.db import models
def index(request):
data={"user":"test001","msg":"this is test index view "}
js=json.dumps(data)
return HttpResponse(js) def stuTable(request):
import time
time.sleep(3)
# stu_object=Student.objects.all()
# return render(request,template_name="index.html",context={"student_object":stu_object})
return HttpResponse(json.dumps({"A":888,"NN":899}))
async 异步协程进阶的更多相关文章
- Python爬虫进阶 | 异步协程
一.背景 之前爬虫使用的是requests+多线程/多进程,后来随着前几天的深入了解,才发现,对于爬虫来说,真正的瓶颈并不是CPU的处理速度,而是对于网页抓取时候的往返时间,因为如果采用request ...
- 深入理解协程(三):async/await实现异步协程
原创不易,转载请联系作者 深入理解协程分为三部分进行讲解: 协程的引入 yield from实现异步协程 async/await实现异步协程 本篇为深入理解协程系列文章的最后一篇. 从本篇你将了解到: ...
- 【Python3爬虫】使用异步协程编写爬虫
一.基本概念 进程:进程是一个具有独立功能的程序关于某个数据集合的一次运行活动.进程是操作系统动态执行的基本单元. 线程:一个进程中包含若干线程,当然至少有一个线程,线程可以利用进程所拥有的资源.线程 ...
- 消息/事件, 同步/异步/协程, 并发/并行 协程与状态机 ——从python asyncio引发的集中学习
我比较笨,只看用await asyncio.sleep(x)实现的例子,看再多,也还是不会. 已经在unity3d里用过coroutine了,也知道是“你执行一下,主动让出权限:我执行一下,主动让出权 ...
- python协程与异步协程
在前面几个博客中我们一一对应解决了消费者消费的速度跟不上生产者,浪费我们大量的时间去等待的问题,在这里,针对业务逻辑比较耗时间的问题,我们还有除了多进程之外更优的解决方式,那就是协程和异步协程.在引入 ...
- python爬虫--多任务异步协程, 快点,在快点......
多任务异步协程asyncio 特殊函数: - 就是async关键字修饰的一个函数的定义 - 特殊之处: - 特殊函数被调用后会返回一个协程对象 - 特殊函数调用后内部的程序语句没有被立即执行 - 协程 ...
- python爬虫---单线程+多任务的异步协程,selenium爬虫模块的使用
python爬虫---单线程+多任务的异步协程,selenium爬虫模块的使用 一丶单线程+多任务的异步协程 特殊函数 # 如果一个函数的定义被async修饰后,则该函数就是一个特殊的函数 async ...
- 异步协程asyncio+aiohttp
aiohttp中文文档 1. 前言 在执行一些 IO 密集型任务的时候,程序常常会因为等待 IO 而阻塞.比如在网络爬虫中,如果我们使用 requests 库来进行请求的话,如果网站响应速度过慢,程序 ...
- asyncio模块实现单线程-多任务的异步协程
本篇介绍基于asyncio模块,实现单线程-多任务的异步协程 基本概念 协程函数 协程函数: 定义形式为 async def 的函数; aysnc 在Python3.5+版本新增了aysnc和awai ...
随机推荐
- 解读Ubuntu的sources.list 和soucres.litsd
使用过Ubuntu的道友们都知道,默认地址是乌班图的org 配置的,对于国内长途跋涉的各位高手来讲真是艰辛: 所以我们一般在安装的时候会先修改服务器源地址使用国内的比如ali,清华或者华为的 源文件地 ...
- Data Manipulation with dplyr in R
目录 select The filter and arrange verbs arrange filter Filtering and arranging Mutate The count verb ...
- 实现ENSP模拟器与物理主机、虚拟机通信
一.环境描述 我需要实现华为模拟器中的网络设备和物理主机.虚拟机通信.这篇文章中以ENSP中的路由器为例,实现它和物理主机.虚拟机的通信. 二.实现方法 在ENSP中借助Cloud来实现. 在Clo ...
- 组合数取mod
组合数取mod 条件mod是质数,inv 是逆元,fac是阶层: 用于n在10^5左右 maxn=100505: ll fact[maxn],inv[maxn]; ll Pow(ll x,ll n){ ...
- linq和初始化器
对象初始化器 在没有初始化器之前,我们初始化一个对象可能需要在构造函数内对属性赋值,或者先实例化一个对象,在一个一个的对其属性赋值. 使用初始化器: 已知类型:var query = new Pers ...
- Allegro 反射仿真--仿真设置
一.打开BRD文件 打开PCB SI,启动Cadence Product Choices界面,如图1-1所示,一般我们选择Allegro PCB SI 630(SPECCTRAQuest),具体如下图 ...
- flume--exec源
创建a2.conf文件并且编写 Sources 类型是exec 配置文件如下 启动集群 启动flume 产生临时文件 ...tmp 关闭临时文件 再次写入文本,会再次产生一个临时文件.截图左边是一个内 ...
- 2.17NOIP模拟赛(by hzwer) T3 小奇回地球
[题目背景] 开学了,小奇在回地球的路上,遇到了一个棘手的问题. [问题描述] 简单来说,它要从标号为 1 的星球到标号为 n 的星球,某一些星球之间有航线. 由于超时空隧道的存在,从一个星球到另一个 ...
- node.js 和 yarn 安装
电脑环境 windows10 专业版 64 位 node.js 安装 Node.js 官方网站下载:https://nodejs.org/en/ 之后一步步得傻瓜式安装 配置环境变量和查看node.j ...
- codeforces 962F.simple cycle(tarjan/点双连通分量)
题目连接:http://codeforces.com/contest/962/problem/F 题目大意是定义一个simple cycle为从一个节点开始绕环走一遍能经过simple cycle内任 ...