python进阶------进程线程(四)
Python中的协程
协程,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程。
协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:
协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。
一、yield实现协程
import time
def consumer():
"""consumer 是一个生成器函数,任何包含yield的函数都是生成器对象"""
r=''
while True:
#consumer 函数通过yield拿到消息,处理又把yield的结果返回给produce生产者。
n=yield r#yield 指令具有return关键字的作用。然后函数的堆栈会自动冻结在这一行。
if not n:#当函数的调用者下一次利用next()或者.send()或者for in 来迭代调用该函数的时候,
return#就会出yield代码的下一行开始,继续执行,再返回下一次的迭代结果。通过这种方式,迭代器可以实现无限序列和惰性求值。
print('[CONSUMER] ←← Consuming %s...' % n)
time.sleep(1)
r = 'consume over' def produce(c):
#首先调用next来启动生成器函数。(consumer)
next(c)
n=0
while n<5:
n = n+1
print('[PRODUCER] →→ Producing %s...' % n)
#一生产了东西就会通过c.send(n)切换到consumer执行
cr = c.send(n)
print('[PRODUCER] Consumer return: %s' % cr)
#produce 不生产了,通过s.close()关闭consumer,整个过程结束
c.close() if __name__ == '__main__':
#通过yield实现的协程的功能整个流程无锁,由一个线程执行,produce和consumer 协作完成任务,并非多线程来抢占任务,将切换变为可控执行的顺序也自然可控最后都是生产者生产一个消费者消费一个。
c = consumer()
produce(c)
二、greenlet
greenlet机制的主要思想是:生成器函数或者协程函数中的yield语句挂起函数的执行,直到稍后使用next()或send()操作进行恢复为止。可以使用一个调度器循环在一组生成器函数之间协作多个任务。greentlet是python中实现我们所谓的"Coroutine(协程)"的一个基础库。
from greenlet import greenlet
def test1():
print (12)
gr2.switch()
print (34)
gr2.switch()
def test2():
print (56)
gr1.switch()
print (78)
gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()
三、基于greenlet的框架
1.1gevent实现协程
Python通过yield提供了对协程的基本支持,但是不完全。而第三方的gevent为Python提供了比较完善的协程支持。
gevent是第三方库,通过greenlet实现协程,其基本思想是:
当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。
由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一些标准库,这一过程在启动时通过monkey patch完成:
monkey 可以使一些阻塞的模块变得不在阻塞,机制:遇到IO操作时则自动切换,手动切换的话只能用到gevent.sleep(0)
from gevent import monkey
monkey.patch_all()
import gevent
from urllib import request
import time
def f(url):
print('GET: %s' % url)
resp = request.urlopen(url)
data = resp.read()
print('%d bytes received from %s.' % (len(data), url))
start=time.time()
gevent.joinall([
gevent.spawn(f, 'https://itk.org/'),
gevent.spawn(f, 'https://www.github.com/'),
gevent.spawn(f, 'https://zhihu.com/'),
])
# f('https://itk.org/')
# f('https://www.github.com/')
# f('https://zhihu.com/')
print(time.time()-start)
用法:
gevent.spawn(函数名称,函数参数):开启协程
gevent.joinall停止协程。
四、协程的优缺点
协程的好处:
无需线程上下文切换的开销
无需原子操作锁定及同步的开销
方便切换控制流,简化编程模型
高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。
缺点:
无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。
进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序
python进阶------进程线程(四)的更多相关文章
- python进阶-------进程线程(二)
Python中的进程线程(二) 一.python中的"锁" 1.GIL锁(全局解释锁) 含义: Python中的线程是操作系统的原生线程,Python虚拟机使用一个全局解释器锁(G ...
- python进阶------进程线程(一)
Python中的进程线程 一.进程线程的概念 1.1进程: 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及 ...
- python进阶------进程线程(五)
Python中的IO模型 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别 ...
- python进阶------进程线程(三)
python中的进程 1.multiprocessing模块 由于GIL的存在,python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进 ...
- python进阶——进程/线程/协程
1 python线程 python中Threading模块用于提供线程相关的操作,线程是应用程序中执行的最小单元. #!/usr/bin/env python # -*- coding:utf-8 - ...
- Python进阶----进程之间通信(互斥锁,队列(参数:timeout和block),), ***生产消费者模型
Python进阶----进程之间通信(互斥锁,队列(参数:timeout和block),), ***生产消费者模型 一丶互斥锁 含义: 每个对象都对应于一个可称为" 互斥锁&qu ...
- Python进阶----进程间数据隔离, join阻塞等待, 进程属性, 僵尸进程和孤儿进程, 守护进程
Python进阶----进程间数据隔离, join阻塞等待, 进程属性, 僵尸进程和孤儿进程, 守护进程 一丶获取进程以及父进程的pid 含义: 进程在内存中开启多个,操作系统如何区分这些进程, ...
- *****Python之进程线程*****
Python之进程线程 Python的threading模块 并发编程: 操作系统:位于底层硬件与应用软件之间的一层. 工作方式:向下管理硬件,向上提供接口. 进程:资源管理单位(容器) 线程:最 ...
- python进阶之 线程编程
1.进程回顾 之前已经了解了操作系统中进程的概念,程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程 ...
随机推荐
- python之爬虫
一.从网页爬下字符串清除特殊字符 import re def validateTitle(title): rstr = r"[\/\\\:\*\?\"\<\>\|\t] ...
- javascript 三种弹出对话框
第一种:alert()方法 第二种:confirm()方法 返回一个布尔值,根据返回的值可以执行相应操作. 第三种: prompt()方法 返回输入的消息,或者其默认值提示框经常用于提示用户在进入页面 ...
- iKcamp出品|微信小程序|工具安装+目录说明|基于最新版1.0开发者工具初中级教程分享
iKcamp官网:http://www.ikcamp.com 访问官网更快阅读全部免费分享课程:<iKcamp出品|全网最新|微信小程序|基于最新版1.0开发者工具之初中级培训教程分享>. ...
- ios自定义数字键盘
因为项目又一个提现的功能,textfiled文本框输入需要弹出数字键盘,首先想到的就是设置textfiled的keyboardType为numberPad,此时你会看到如下的效果: 但是很遗憾这样 ...
- 关于scanf 与 cin gets(),getline()......输入输出字符串的区别
很对人对于字符串的输入输出一直是比较模糊的,今天总结一下几个常用的输入流符号对于输入字符串时的区别: 1.scanf(),首先 它遇到空格或回车键(\n)就会结束,并且会将回车符算入字符串中: 2.c ...
- 【网络爬虫入门05】分布式文件存储数据库MongoDB的基本操作与爬虫应用
[网络爬虫入门05]分布式文件存储数据库MongoDB的基本操作与爬虫应用 广东职业技术学院 欧浩源 1.引言 网络爬虫往往需要将大量的数据存储到数据库中,常用的有MySQL.MongoDB和Red ...
- Hibernate 一对一双向映射 注解方式
有外键的一方: @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "courseid") public Tcourse ge ...
- 已安装Fedora的U盘无法格式化,要求reinitialize layout
错误提示:This partition cannot be modified because it contains a partition table; >please reinitializ ...
- IOS 中的JS
文章摘自: http://www.cocoachina.com/ios/20150127/11037.html JSContext/JSValue JSContext 即JavaScript代码的 ...
- 给资源文件添加指纹(Gulp版)
至于为什么要费尽心思地给文件添加指纹,请参看前端静态资源缓存控制策略.这次要达到的小目标就是生成的资源文件能够被客户端缓存,而在文件内容变化后,能够请求到最新的文件. 需要用到的 gulp 插件是 g ...