Python学习---协程 1226
协程【是一个单线程】,又称微线程,纤程。英文名Coroutine。
一句话说明什么是协程:协程是一种用户态的轻量级线程【程序员自己去切换线程】
协程条件:
必须在只有一个单线程里实现并发
修改共享数据不需加锁
用户程序里自己保存多个控制流的上下文栈
一个协程遇到IO操作自动切换到其它协程
协程原理:
协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:
协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。
协程的好处【Nginx就是协程】:
无需线程上下文切换的开销【单线程】
无需原子操作锁定及同步的开销
"原子操作(atomic operation)是不需要synchronized",所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序是不可以被打乱,或者切割掉只执行部分。视作整体是原子性的核心。
方便切换控制流,简化编程模型
高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理
协程缺点:
无法利用多核资源【可以通过多进程实现多核利用】:协程的本质是个单线程,它不能同时将单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。
进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序
最底层实际上使用yield实现协程操作
import time
import queue
def consumer(name):print("--->starting eating baozi...")while True:new_baozi = yieldprint("[%s] is eating baozi %s" % (name, new_baozi))# time.sleep(1)
def producer():r = con.__next__()r = con2.__next__()n = 0while n < 5:n += 1con.send(n)con2.send(n)print("\033[32;1m[producer]\033[0m is making baozi %s" % n)
if __name__ == '__main__':con = consumer("c1")con2 = consumer("c2")p = producer()
gevent
安装gevent
Gevent 介绍
Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。 Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。
import gevent
import time
def func1():print(time.ctime(), '\033[31;1mA-->B...\033[0m')gevent.sleep(2) # 模拟IO阻塞print(time.ctime(), '\033[31;1mA-->B...\033[0m')
def func2():print(time.ctime(), '\033[32;1mB-->A...\033[0m')gevent.sleep(1) # 模拟IO阻塞print(time.ctime(), '\033[32;1mB-->A...\033[0m')
# 一个线程自己切换,共耗时2秒,以最大的为准
gevent.joinall([gevent.spawn(func1),gevent.spawn(func2),
])
Greenlet
greenlet是一个用C实现的协程模块,相比与python自带的yield,它可以使你在任意函数之间随意切换,而不需把这个函数先声明为generator
# -*- coding:utf-8 -*-
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()
协程爬虫
遇到IO阻塞时会自动切换任务[协程爬虫]
from gevent import monkey;
monkey.patch_all() # 监听IO阻塞
import time
import gevent
from urllib.request import urlopen
start = time.time()
def f(url, name):print('GET: %s' % url)resp = urlopen(url)data = resp.read()with open(name+'.thml', 'wb') as f:f.write(data)print('%d bytes received from %s.' % (len(data), url))
gevent.joinall([gevent.spawn(f, 'https://www.python.org/', 'python'), # 就是这种格式传递参数gevent.spawn(f, 'https://www.yahoo.com/', 'yahoo'),gevent.spawn(f, 'https://github.com/', 'github'),
])
end = time.time()
print('gevent 耗时', str(end-start))
【更多参考】
http://www.cnblogs.com/alex3714/articles/5248247.html
转载于:https://www.cnblogs.com/ftl1012/p/9384297.html
Python学习---协程 1226相关推荐
- Python 的协程库 greenlet 和 gevent
greenlet 官方文档:https://greenlet.readthedocs.io/en/latest/ From:https://www.jianshu.com/u/3ab212f28d91 ...
- python3 协程 写法_理解Python的协程(Coroutine)
由于GIL的存在,导致Python多线程性能甚至比单线程更糟. GIL: 全局解释器锁(英语:Global Interpreter Lock,缩写GIL),是计算机程序设计语言解释器用于同步线程的一种 ...
- python携程使用_简单了解python gevent 协程使用及作用
简介 没有切换开销.因为子程序切换不是线程切换,而是由程序自身控制,没有线程切换的开销,因此执行效率高, 不需要锁机制.因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断 ...
- python 异步协程爬虫-半次元图片
python 异步协程爬虫-半次元图片 1. 页面分析 2.代码大体构思 3.源码分析 3.1 完成效果 4.异步协程的优势 5.难点分析 6.可扩展性 欢迎私信或评论区交流 爬取网址 : https ...
- 理解Python的协程(Coroutine)
生成器(Generator) yield表达式的使用 生产者和消费者模型 yield from表达式 协程(Coroutine) @asyncio.coroutine async/await 总结 参 ...
- python gevent 协程
python gevent 协程 def func1():print("fun1开始运行")gevent.sleep(2) # 内部函数实现io操作print("func ...
- Python基础入门教程:使用 Python 3 协程快速获得一个代理池
Python基础入门教程:使用 Python 3 协程快速获得一个代理池 前言 在执行 IO 密集型任务的时候,程序会因为等待 IO 而阻塞.比如我们使用 requests 库来进行网络爬虫请求的话, ...
- python中协程与函数的区别_深入浅析python 协程与go协程的区别
进程.线程和协程 进程的定义: 进程,是计算机中已运行程序的实体.程序本身只是指令.数据及其组织形式的描述,进程才是程序的真正运行实例. 线程的定义: 操作系统能够进行运算调度的最小单位.它被包含在进 ...
- python中协程与函数的区别_python 协程与go协程的区别
进程.线程和协程 进程的定义: 进程,是计算机中已运行程序的实体.程序本身只是指令.数据及其组织形式的描述,进程才是程序的真正运行实例. 线程的定义: 操作系统能够进行运算调度的最小单位.它被包含在进 ...
最新文章
- mitmdump脚本中使用requests模块发送请求
- 一直在构建工作空间_基于用户场景构建的建筑工程弱电设计工作设想
- linux x86板级文件,Linux driver 板级文件跟踪一般方法
- java 线程 Thread Runnable 实现样例
- python-函数的参数-位置参数-关键词参数
- 微信小程序的零食商城
- 树莓派 rfid_技术 | 对恶意树莓派设备的取证分析
- 一行一行分析JQ源码学习笔记-03
- 【Hadoop】HDFS三组件:NameNode、SecondaryNameNode和DataNode
- Docker系列(四)守护式容器
- 孙鑫VC学习笔记:第二讲 掌握C++
- 阿里云播放器组件 vue-aliplayer
- W3Cschool菜鸟教程离线版下载链接
- 算法分析与设计课程总结
- Windows javaw进程占用cpu资源100% 导致电脑卡顿
- Facebook的新算法可以预测出你的贫富阶级
- Ada的故事(转自互联网)
- 学会这招,小姐姐看你的眼神将不一样
- el-table设置表头样式,在table行间加入
- tampermonkey如何寻找_Tampermonkey脚本安装问题及自用脚本推荐