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.线程简述: 一条流水线的执行过程是一个线程,一条流水线必须属于一个车间,一个车间的运行过程就是一个进程(一个进程内至少一个 ...
随机推荐
- Mybatis学习系列(五)关联查询
前面几节的示例基本都是一些单表查询,实际项目中,经常用到关联表的查询,比如一对一,一对多等情况.在Java实体对象中,一对一和一对多可是使用包装对象解决,属性使用List或者Set来实现,在mybat ...
- Java堆和栈
栈中存基本类型变量数据和对象的引用 堆中存new的对象
- RadioGroup和GroupBox有什么区别?
我在RadioGroup中放RadioButton和GroupBox中一样,搞不明白. radiogroup有个item属性都是radio控件,不需要拖控件上去.groupbox需要自己拖控件 分组的 ...
- ELK6.2.4集群
ELK6.2.4集群安装使用 https://www.cnblogs.com/frankdeng/p/9139035.html 一 简介 Elasticsearch是一个高度可扩展的开源全文搜索和分析 ...
- NET中解决KafKa多线程发送多主题
NET中解决KafKa多线程发送多主题 一般在KafKa消费程序中消费可以设置多个主题,那在同一程序中需要向KafKa发送不同主题的消息,如异常需要发到异常主题,正常的发送到正常的主题,这时候就需要实 ...
- Spark程序
Spark认识&环境搭建&运行第一个Spark程序 2017-07-09 17:17 by 牛仔裤的夏天, 181 阅读, 0 评论, 收藏, 编辑 摘要:Spark作为新一代大数据计 ...
- poj 2155 Matrix (树状数组)
Matrix Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 16797 Accepted: 6312 Descripti ...
- 设计模式开篇综述(Java)
设计原则是规范,设计模式是技巧.如果在项目中能够灵活运用这些基础知识,那么我相信一定会得到意想不到的收获. 接下来的时间里,我将继续学习设计模式,将对每一个设计模式从以下几点进行分析和学习,如有不妥当 ...
- 二进制转16进制JAVA代码
public class Binary2Hex { public static void main(String[] args) { String bString ="10101000&qu ...
- xcode 10 出现 :-1: Multiple commands produce '/Users/.../Library/Developer/Xcode/DerivedData/.../Build/Products/Dev-iphonesimulator/TLYShyNavBar/TLYShyNavBar.framework/Info.plist': 1) Target 'TLYShyNavB
错误提示如下: :-1: Multiple commands produce '/Users/.../Library/Developer/Xcode/DerivedData/.../Build/Pro ...