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.线程简述: 一条流水线的执行过程是一个线程,一条流水线必须属于一个车间,一个车间的运行过程就是一个进程(一个进程内至少一个 ...
随机推荐
- Mac下安装OpenCV问题
最近看了纹理特征方面的paper,看了一些资料之后,想要实际动手实现一下其中LBP算法,果然OpenCV中已经实现. 问题 No module named "cv2" 当我在我们项 ...
- System.NullReferenceException:未将对象引用设置到对象的实例,这是一个新鸟,中鸟,老鸟都避不开的错误
原文链接:http://www.jb51.net/article/30005.htm
- JVM(1)——简介
网上流传着一段挺有意思的话-- 对于从事C或C++的开发人员来说,他们既是内存管理的最高权力的皇帝,也是最基础的劳动人民,担负着每一个对象生命开始到终结的维护工作,有点光杆司令的赶脚. 但对于java ...
- js 给某个div增加class 样式(三种方式)
第一种: el.setAttribute('class','abc'); <!DOCTYPE HTML> <HTML> <HEAD> <meta c ...
- HTML5<canvas>标签:简单介绍(0)
<canvas> 标签是 HTML 5 中的新标签,像所有的dom对象一样它有自己本身的属性.方法和事件, 其中就有绘图的方法,js能够调用它来进行绘图 ,最近在研读<html5与c ...
- P1196 [NOI2002]银河英雄传说
题目描述 公元五八○一年,地球居民迁至金牛座α第二行星,在那里发表银河联邦创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七九九年,银河系的两大军事集团在巴米利恩星域爆发战争.泰山压顶 ...
- HDU 6208 The Dominator of Strings(AC自动机)
The Dominator of Strings Time Limit: 3000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java ...
- 【BZOJ 3316】JC loves Mkk 01分数规划+单调队列
单调栈不断吞入数据维护最值,数据具有单调性但不保证位置为其排名,同时可以按照进入顺序找出临近较值单调队列队列两端均可删除数据但只有队末可以加入数据,仍然不断吞入数据但同时可以额外刨除一些不符合条件的数 ...
- 收藏一个漂亮的Flash焦点图切换
网上闲逛的时候发现一个Flash焦点图效果,跟喜欢,然后就下载回来,收集在这里,以便以后方便取用.这个Flash使用方法也是相当简单的,如果你喜欢,也可以从这里查看源代码下载. Flash 焦点图效果 ...
- python监控服务器
import paramikoimport threadingimport reimport timeimport stringfrom sendmail import send_maildef ss ...