python-day37--协程
一、 协程介绍
单线程下实现并发,提升运行效率,
1.自己控制切换,保存状态
2.遇到I/O切 (单纯的CPU切没意义,只有在遇到I/O的时候切才有效率)
一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。、
需要强调的是:
#1. python的线程属于内核级别的,即由操作系统控制调度(如单线程遇到io或执行时间过长就会被迫交出cpu执行权限,切换其他线程运行)
#2. 单线程内开启协程,一旦遇到io,就会从应用程序级别(而非操作系统)控制切换,以此来提升效率(!!!非io操作的切换与效率无关)
对比操作系统控制线程的切换,用户在单线程内控制协程的切换
优点如下:
#1. 协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级
#2. 单线程内就可以实现并发的效果,最大限度地利用cpu
缺点如下:
#1. 协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程
#2. 协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程
总结协程特点:
- 必须在只有一个单线程里实现并发
- 修改共享数据不需加锁
- 用户程序里自己保存多个控制流的上下文栈
- 附加:一个协程遇到IO操作自动切换到其它协程(如何实现检测IO,yield、greenlet都无法实现,就用到了gevent模块(select机制))
二、用yeild实现协程
import time
def init(func):
def wrapper(*args,**kwargs):
g=func(*args,**kwargs)
next(g)
return g
return wrapper
@init
def consumer():
while True:
x=yield
print(x) def producer(target):
for i in range(10):
# time.sleep(1)
target.send(i) producer(consumer())
三、greenlet模块(了解就行,遇到I/O不能切)
from greenlet import greenlet
import time
def eat(name):
print('%s eat 1' %name)
time.sleep(10) #在io阻塞的时候 不能来回切,会一直在这睡着
g2.switch('egon')
print('%s eat 2' %name)
g2.switch()
def play(name):
print('%s play 1' %name)
g1.switch()
print('%s play 2' %name) g1=greenlet(eat)
g2=greenlet(play) #g1.switch('egon')#可以在第一次switch时传入参数,以后都不需要
四、gevent模块
遇到IO阻塞时会自动切换任务
用法
#用法
g1=gevent.spawn(func,1,,2,3,x=4,y=5)创建一个协程对象g1,spawn括号内第一个参数是函数名,如eat,后面可以有多个参数,可以是位置实参或关键字实参,都是传给函数eat的 g2=gevent.spawn(func2) g1.join() #等待g1结束 g2.join() #等待g2结束 #或者上述两步合作一步:gevent.joinall([g1,g2]) g1.value#拿到func1的返回值
from gevent import monkey;monkey.patch_all() #monkey;monkey.patch_all() 可以识别其他的I/O操作
import gevent
import time,threading
def eat(name):
print('%s eat 1' %name)
time.sleep(2)
print('%s eat 2' %name)
return 'eat' def play(name):
print('%s play 1' %name)
time.sleep(3)
print('%s play 2' %name)
return 'play' start=time.time()
g1=gevent.spawn(eat,'egon')
g2=gevent.spawn(play,'egon')
# g1.join()
# g2.join()
gevent.joinall([g1,g2])
print('主',(time.time()-start))
print(g1.value)
print(g2.value) # 结果:
egon eat 1
egon play 1
egon eat 2
egon play 2
主 3.0018091201782227
eat
play
五、协程的应用
练习题1
from gevent import monkey;monkey.patch_all()
import gevent
import requests
import time def get_page(url):
print('GET: %s' %url)
response=requests.get(url)
if response.status_code == 200:
print('%d bytes received from %s' %(len(response.text),url)) start_time=time.time() # get_page('https://www.python.org/') #串行
# get_page('https://www.yahoo.com/') #串行
# get_page('https://github.com/') #串行 g1=gevent.spawn(get_page, 'https://www.python.org/')
g2=gevent.spawn(get_page, 'https://www.yahoo.com/')
g3=gevent.spawn(get_page, 'https://github.com/') gevent.joinall([g1,g2,g3])
stop_time=time.time()
print('run time is %s' %(stop_time-start_time))
爬虫练习
练习题2
from gevent import monkey;monkey.patch_all()
import gevent
from socket import *
def talk(conn,addr):
while True:
data=conn.recv(1024)
print('%s:%s %s' %(addr[0],addr[1],data))
conn.send(data.upper())
conn.close() def server(ip,port):
s = socket(AF_INET, SOCK_STREAM)
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
s.bind((ip,port))
s.listen(5)
while True:
conn,addr=s.accept()
gevent.spawn(talk,conn,addr)
s.close() if __name__ == '__main__':
server('127.0.0.1', 8088)
并发通信 服务端
from multiprocessing import Process
from socket import *
def client(server_ip,server_port):
client=socket(AF_INET,SOCK_STREAM)
client.connect((server_ip,server_port))
while True:
cmd=input('')
client.send(cmd.encode('utf-8'))
msg=client.recv(1024)
print(msg.decode('utf-8')) if __name__ == '__main__':
client('127.0.0.1', 8088)
并发通信 客户端
python-day37--协程的更多相关文章
- python gevent 协程
简介 没有切换开销.因为子程序切换不是线程切换,而是由程序自身控制,没有线程切换的开销,因此执行效率高, 不需要锁机制.因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断 ...
- 深入理解Python中协程的应用机制: 使用纯Python来实现一个操作系统吧!!
本文参考:http://www.dabeaz.com/coroutines/ 作者:David Beazley 缘起: 本人最近在学习python的协程.偶然发现了David Beazley的co ...
- 关于Python的协程问题总结
协程其实就是可以由程序自主控制的线程 在python里主要由yield 和yield from 控制,可以通过生成者消费者例子来理解协程 利用yield from 向生成器(协程)传送数据# 传统的生 ...
- {python之协程}一 引子 二 协程介绍 三 Greenlet 四 Gevent介绍 五 Gevent之同步与异步 六 Gevent之应用举例一 七 Gevent之应用举例二
python之协程 阅读目录 一 引子 二 协程介绍 三 Greenlet 四 Gevent介绍 五 Gevent之同步与异步 六 Gevent之应用举例一 七 Gevent之应用举例二 一 引子 本 ...
- 【Python】协程
协程,又称微线程,纤程.英文名Coroutine. 协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用. 子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在 ...
- Python之协程(coroutine)
Python之协程(coroutine) 标签(空格分隔): Python进阶 coroutine和generator的区别 generator是数据的产生者.即它pull data 通过 itera ...
- python的协程和_IO操作
协程Coroutine: 协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行. 注意,在一个子程序中中断,去执行其他子程序,不是函数调用,有点 ...
- python 3 协程函数
python 3 协程函数 1:把函数的执行结果封装好__iter__和__next__,即得到一个迭代器 2:与return功能类似,都可以返回值,但不同的是,return只能返回一次值,而yiel ...
- Python之协程函数
Python之协程函数 什么是协程函数:如果一个函数内部yield的使用方法是表达式形式的话,如x=yield,那么该函数成为协程函数. def eater(name): print('%s star ...
- 多任务-python实现-协程(2.1.11)
多任务-python实现-协程(2.1.11) 23/100 发布文章 qq_26624329 @ 目录 1.概念 2.迭代器 1.概念 协程与子例程一样,协程(coroutine)也是一种程序组件. ...
随机推荐
- keepalived+lvs高可用集群
LVS+Keepalived 介绍 LVS LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统.本项目在1998年5月由章文嵩博士成立,是中国 ...
- PHP中private和public还有protected的区别
原文链接:http://www.thinkphp.cn/code/1898.html <? //父类 class father{ public function a(){ echo " ...
- 20145101 《Java程序设计》第7周学习总结
20145101<Java程序设计>第7周学习总结 教材学习内容总结 第十二章 Lambda Lambda表达式中this的参考对象以及toString()的接受者,是来自Lambda的周 ...
- 20145335郝昊《网络对抗》Exp 8 Web基础
20145335郝昊<网络对抗>Exp 8 Web基础 实验内容 本实践的具体要求有: Web前端HTML:能正常安装.启停Apache.理解HTML,理解表单,理解GET与POST方法, ...
- 20165310_Exp2实验三《敏捷开发与XP实践》
20165310 java_exp3 敏捷开发与XP实践 一.编码标准 编程标准包含:具有说明性的名字.清晰的表达式.直截了当的控制流.可读的代码和注释,以及在追求这些内容时一致地使用某些规则和惯用法 ...
- 自定义LisetView
1.ListView listview=findViewById(R.id.listview); 2.public class MyAdapter extends BaseAdapter{ priva ...
- POJ 3694 Network(并查集缩点 + 朴素的LCA + 无向图求桥)题解
题意:给你一个无向图,有q次操作,每次连接两个点,问你每次操作后有几个桥 思路:我们先用tarjan求出所有的桥,同时我们可以用并查集缩点,fa表示缩点后的编号,还要记录每个节点父节点pre.我们知道 ...
- BZOJ3942: [Usaco2015 Feb]Censoring 栈+KMP
Description Farmer John has purchased a subscription to Good Hooveskeeping magazine for his cows, so ...
- BZOJ4419: [Shoi2013]发微博 暴力
Description 刚开通的SH微博共有n个用户(1..n标号),在短短一个月的时间内,用户们活动频繁,共有m条按时间顺序的记录: ! x 表示用户x发了一条微博: + x y 表示用户x和用 ...
- 51nod 1199 Money out of Thin Air(线段树+树剖分)
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1199 题意: 思路:因为是一棵树,所以需要把它剖分一下再映射到线段树上, ...