Python 进阶 之 协程
协程的概念级描述(与线程对比):转自知乎 链接
线程有两个必须要处理的问题:一是碰着阻塞式I\O会导致整个进程被挂起;
二是由于缺乏时钟阻塞,进程需要自己拥有调度线程的能力。
如果一种实现使得每个线程需要自己通过调用某个方法,主动交出控制权。那么我们就称这种线程是协作式的,即是协程。
在Python中关于协程的实现方式有三种:
- 最初的生成器变形yield/send
- 引入@asyncio.coroutine和yield from
- 在Python3.5版本中引入async/await关键字
以下代码均在Centos 7 Python3.6调试通过!
简单的yield使用描述:
def fun():
index = 0
while True:
yield index
index += 1
if index > 3 :
break
for i in fun():
print (i)
输出:0 1 2 3
在此例中yield做的事是:
1:将函数fun的返回值设定为一个生成器
2:每次运行至yield index 时会将index的值作为生成器的下一个元素返回值for循环并且被赋值给变量i,用print输出出来
简单的yield/send使用描述:
def fun():
index = 0
while True:
value = yield index
print ("value=" + str(value))
print ("index=" + str(index))
index += 1
if index > 3 :
break
funobj = fun()
print (type(funobj))
print ("next=" + str(next(funobj)))
for i in funobj:
print ("i=" + str(i))
try:
funobj.send(i+100)
except StopIteration:
print("it's stop")
输出:
<class 'generator'>
next=0
value=None
index=0
i=1
value=101
index=1
value=None
index=2
i=3
value=103
index=3
it's stop
不是很精通,因此代码有点乱。
解释:
首先声明了fun函数,并将fun赋给了对面funobj,funobj是一个迭代器。next(funobj)初始化并启动迭代器,程序开始运行fun函数至value = yield index(第一次)结束,yield返回了第一个index值0 next=0
for i in funobj:启动迭代器,因此此时send还未传值,因此value和next都是空,value=None index=0 程序运行fun函数至value = yield index(第二次)结束,yield返回了第二个index值1 i=1
注意之后send发送了值101,for再次启动迭代器,从yield启动时捕获到此值101,value=101 index=101。此后类似。
迭代器结束时会捕获到 StopIteration异常,将此捕获并输出出来 it's stop
简单的yield/send使用描述:
yeild from语法就是将生成器函数中包括yield语句的部分逻辑封装到一个子生成器函数中。然后在子生成器函数外面可以做一些其他的业务逻辑。整个生成器函数(包括子生成器函数)对外就是一个生成器函数。
def fun():
index = 0
while True:
value = yield index
print ("value=" + str(value))
print ("index=" + str(index))
index += 1
if index > 3 :
break def fun2():
print ("before ")
yield from fun()
print ("end ") funobj = fun2()
print (type(funobj))
print ("next=" + str(next(funobj)))
for i in funobj:
print ("i=" + str(i))
try:
funobj.send(i+100)
except StopIteration:
print("it's stop")
输出:
<class 'generator'>
before
next=0
value=None
index=0
i=1
value=101
index=1
value=None
index=2
i=3
value=103
index=3
end
it's stop
简单的asyncio.coroutine使用描述:(参考自廖雪峰的官方网站)
@asyncio.coroutine通过装饰器调用,作用是把一个generator标记为coroutine类型:
import asyncio @asyncio.coroutine
def hello():
print("Hello world!")
# 异步调用asyncio.sleep(1):
r = yield from asyncio.sleep(1)
print("Hello again!") # 获取EventLoop:
loop = asyncio.get_event_loop()
# 执行coroutine
loop.run_until_complete(hello())
loop.close()
输出:
Hello world!
Hello again!
简单的async和await使用描述:
async和await是针对coroutine的新语法,要使用新的语法,只需要做两步简单的替换:
- 把
@asyncio.coroutine替换为async; - 把
yield from替换为await。
示例代码:
import asyncio async def hello():
print("Hello world!")
r = await asyncio.sleep(1)
print("Hello again!") # 获取EventLoop:
loop = asyncio.get_event_loop()
# 执行coroutine
loop.run_until_complete(hello())
loop.close()
需要注意的是async和await只能用在Python 3.5以及后续版本,如果使用3.4版本,则仍需使用asyncio.coroutine和yield from方案。
示例可能出现的报错如下:
[root@jans test]# python3.6 c.py
Hello world!
Hello again!
[root@jans test]# python3.4 c.py
File "c.py", line 3
async def hello():
^
SyntaxError: invalid syntax
Python 进阶 之 协程的更多相关文章
- Python自动化 【第十篇】:Python进阶-多进程/协程/事件驱动与Select\Poll\Epoll异步IO
本节内容: 多进程 协程 事件驱动与Select\Poll\Epoll异步IO 1. 多进程 启动多个进程 进程中启进程 父进程与子进程 进程间通信 不同进程间内存是不共享的,要想实现两个进程间 ...
- Python进阶:聊协程
从一个爬虫说起 Python 2 的时代使用生成器协程,Python 3.7 提供了新的基于 asyncio 和 async / await 的方法.先看一个简单的爬虫代码,爬虫的 scrawl_pa ...
- 第十一章:Python高级编程-协程和异步IO
第十一章:Python高级编程-协程和异步IO Python3高级核心技术97讲 笔记 目录 第十一章:Python高级编程-协程和异步IO 11.1 并发.并行.同步.异步.阻塞.非阻塞 11.2 ...
- Python中Paramiko协程方式详解
什么是协程 协程我们可以看做是一种用户空间的线程. 操作系统对齐存在一无所知,需要用户自己去调度. 比如说进程,线程操作系统都是知道它们存在的.协程的话是用户空间的线程,操作系统是不知道的. 为什么要 ...
- [转载]Python 3.5 协程究竟是个啥
http://blog.rainy.im/2016/03/10/how-the-heck-does-async-await-work-in-python-3-5/ [译] Python 3.5 协程究 ...
- [译] Python 3.5 协程究竟是个啥
转自:http://blog.rainy.im/2016/03/10/how-the-heck-does-async-await-work-in-python-3-5/ [译] Python 3.5 ...
- python中的协程及实现
1.协程的概念: 协程是一种用户态的轻量级线程.协程拥有自己的寄存器上下文和栈. 协程调度切换时,将寄存器上下文和栈保存到其他地方,在切换回来的时候,恢复先前保存的寄存器上下文和栈. 因此,协程能保留 ...
- Python基础之协程
阅读目录 一 引子 二 协程介绍 三 Greenlet模块 四 Gevent模块 引子 之前我们学习了线程.进程的概念,了解了在操作系统中 进程是资源分配的最小单位,线程是CPU调度的最小单位. 按道 ...
- python线程、协程、I/O多路复用
目录: 并发多线程 协程 I/O多路复用(未完成,待续) 一.并发多线程 1.线程简述: 一条流水线的执行过程是一个线程,一条流水线必须属于一个车间,一个车间的运行过程就是一个进程(一个进程内至少一个 ...
随机推荐
- PHPExcel 导出包含图片excel
<?php // 这里用的PHPExcel版本号为1.8.0 // 下载地址https://github.com/PHPOffice/PHPExcel 下载ZIP压缩包 // 下载后将Class ...
- js把字符串格式的时间转换成几秒前、几分钟前、几小时前、几天前等格式
最近在做项目的时候,需要把后台返回的时间转换成几秒前.几分钟前.几小时前.几天前等的格式:后台返回的时间格式为:2015-07-30 09:36:10,需要根据当前的时间与返回的时间进行对比,最后显示 ...
- Java中WeakHashMap实现原理深究
一.前言 我发现Java很多开源框架都使用了WeakHashMap,刚开始没怎么去注意,只知道它里面存储的值会随时间的推移慢慢减少(在 WeakHashMap 中,当某个“弱键”不再正常使用时,会被从 ...
- 集群hadoop ubuntu版
搭建ubuntu版hadoop集群 用到的工具:VMware.hadoop-2.7.2.tar.jdk-8u65-linux-x64.tar.ubuntu-16.04-desktop-amd64.is ...
- 【bzoj1061】[NOI2008]志愿者招募 线性规划与费用流
题目描述 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者.经过估算,这个项目需要N 天才能完成,其中第i ...
- 【bzoj3262】陌上花开 CDQ分治+树状数组
题目描述 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当且仅当Sa&g ...
- poj 2965 The Pilots Brothers' refrigerator (dfs)
The Pilots Brothers' refrigerator Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 17450 ...
- PowerShell收发TCP消息包
PowerShell收发TCP消息包 https://www.cnblogs.com/fuhj02/archive/2012/10/16/2725609.html 在上篇文章中,我们在PSNet包中创 ...
- [CQOI2012]局部极小值
题目链接 注意到\(4\times 7\)的矩阵的局部极小值最多只有8个,可以状压. 设\(f[i][sta]\)表示从小到大填数,当前填到\(i\),极小值的填充状态为\(sta\)的方案数. 考虑 ...
- Could not resolve com.android.support:multidex:1.0.2
http://blog.csdn.net/goodlixueyong/article/details/50992835