一、 协程介绍

单线程下实现并发,提升运行效率,

  1.自己控制切换,保存状态

  2.遇到I/O切         (单纯的CPU切没意义,只有在遇到I/O的时候切才有效率)

一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。、

需要强调的是:

#1. python的线程属于内核级别的,即由操作系统控制调度(如单线程遇到io或执行时间过长就会被迫交出cpu执行权限,切换其他线程运行)
#2. 单线程内开启协程,一旦遇到io,就会从应用程序级别(而非操作系统)控制切换,以此来提升效率(!!!非io操作的切换与效率无关)

对比操作系统控制线程的切换,用户在单线程内控制协程的切换

优点如下:

#1. 协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级
#2. 单线程内就可以实现并发的效果,最大限度地利用cpu

缺点如下:

#1. 协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程
#2. 协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程

总结协程特点:

  1. 必须在只有一个单线程里实现并发
  2. 修改共享数据不需加锁
  3. 用户程序里自己保存多个控制流的上下文栈
  4. 附加:一个协程遇到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--协程的更多相关文章

  1. python gevent 协程

    简介 没有切换开销.因为子程序切换不是线程切换,而是由程序自身控制,没有线程切换的开销,因此执行效率高, 不需要锁机制.因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断 ...

  2. 深入理解Python中协程的应用机制: 使用纯Python来实现一个操作系统吧!!

    本文参考:http://www.dabeaz.com/coroutines/   作者:David Beazley 缘起: 本人最近在学习python的协程.偶然发现了David Beazley的co ...

  3. 关于Python的协程问题总结

    协程其实就是可以由程序自主控制的线程 在python里主要由yield 和yield from 控制,可以通过生成者消费者例子来理解协程 利用yield from 向生成器(协程)传送数据# 传统的生 ...

  4. {python之协程}一 引子 二 协程介绍 三 Greenlet 四 Gevent介绍 五 Gevent之同步与异步 六 Gevent之应用举例一 七 Gevent之应用举例二

    python之协程 阅读目录 一 引子 二 协程介绍 三 Greenlet 四 Gevent介绍 五 Gevent之同步与异步 六 Gevent之应用举例一 七 Gevent之应用举例二 一 引子 本 ...

  5. 【Python】协程

    协程,又称微线程,纤程.英文名Coroutine. 协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用. 子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在 ...

  6. Python之协程(coroutine)

    Python之协程(coroutine) 标签(空格分隔): Python进阶 coroutine和generator的区别 generator是数据的产生者.即它pull data 通过 itera ...

  7. python的协程和_IO操作

    协程Coroutine: 协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行. 注意,在一个子程序中中断,去执行其他子程序,不是函数调用,有点 ...

  8. python 3 协程函数

    python 3 协程函数 1:把函数的执行结果封装好__iter__和__next__,即得到一个迭代器 2:与return功能类似,都可以返回值,但不同的是,return只能返回一次值,而yiel ...

  9. Python之协程函数

    Python之协程函数 什么是协程函数:如果一个函数内部yield的使用方法是表达式形式的话,如x=yield,那么该函数成为协程函数. def eater(name): print('%s star ...

  10. 多任务-python实现-协程(2.1.11)

    多任务-python实现-协程(2.1.11) 23/100 发布文章 qq_26624329 @ 目录 1.概念 2.迭代器 1.概念 协程与子例程一样,协程(coroutine)也是一种程序组件. ...

随机推荐

  1. Linux服务器配置---ftp限制带宽

    限制带宽 ftp服务器可以设置每个用户的带宽,这样根据实际需求来分配,更加充分的利用系统资源.带宽通过参数“anon_max_rate“和”local_max_rate“来设置,这两个参数在配置文件中 ...

  2. java输出重定向

    Java的标准输入,输出分别是通过System.in和System.out来代表.默认情况下他们分别代表键盘和显示器. System类里提供了3个重定向标准输入,输出的方法. static void ...

  3. ELK之logstash6.5

    首先安装,这里采用rpm安装: # rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch 创建repo文件: [root@no ...

  4. Vue 父组件循环使用refs调用子组件方法出现undefined的问题

    Vue 父组件循环使用refs调用子组件方法出现undefined的问题 1. 背景 最近前端项目遇到一个问题,我在父组件中使用了两个相同的子组件child,分别设置ref为add和update.其中 ...

  5. deepin linux java开发环境搭建全系列

    一.jdk安装 下载并解压到Java文件,这个文件是我自己放的位置 配置环境变量 第一次使用终端需要设置管理员密码 之后开始设置环境变量 sudo vim /etc/profile :wq 保存并退出 ...

  6. Python3基础 list str转成list

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  7. Python3基础 __delattr__ 在一个属性被删除时的行为

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  8. 打开vi后提示The ycmd server SHUT DOWN (restart with :YcmRestartServer)该如何处理

    答:进入YouCompleteMe的安装目录安装一些必要的依赖 比如:笔者将YouCompleteMe安装到了~/.vim/bundle目录下,那么执行以下操作: cd ~/.vim/bundle/Y ...

  9. windows下启动某程序提示缺失**.dll文件的处理方法

    一.背景: 1.os : windows7 64bit 旗舰版 2.启动ftp服务端软件时提示缺失mfc100.dll文件 以上情形亲测有效 二.修复 2.1 从https://cn.dll-file ...

  10. 2016年蓝桥杯B组C/C++省赛(预选赛)题目解析

    2016年蓝桥杯B组C/C++ 点击查看2016年蓝桥杯B组省赛试题(无答案版) 第一题:煤球数目 题解 有一堆煤球,堆成三角棱锥形.具体: 第一层放1个, 第二层3个(排列成三角形), 第三层6个( ...