Python 之协程
多线程并发、包括线程池,是操作系统控制的并发。如果是单线程,可以通过协程实现单线程下的并发。
协程 又称微线程,是一种用户态的轻量级线程,由用户程序自己控制调度。
python的线程属于内核级别的,由操作系统控制调度(如单线程遇到io或执行时间过长就会被迫交出cpu执行权限,切换其他线程运行)
而单线程里开启协程,一旦遇到io,由用户自己控制调度。
特点:
1、单线程里并发
2、修改共享数据不需枷锁
3、用户程序里保存多个控制流的上下文栈
4、附加:一个协程遇到IO操作自动切换到其他协程(yield,greenlet都无法实现检测IO,用gevent模块的select机制可以)
并发:
# 注意到consumer函数是一个generator(生成器): # 任何包含yield关键字的函数都会自动成为生成器(generator)对象 def consumer():r = ''while True:# 3、consumer通过yield拿到消息,处理,又通过yield把结果传回;# yield指令具有return关键字的作用。然后函数的堆栈会自动冻结(freeze)在这一行。# 当函数调用者的下一次利用next()或generator.send()或for-in来再次调用该函数时,# 就会从yield代码的下一行开始,继续执行,再返回下一次迭代结果。通过这种方式,迭代器可以实现无限序列和惰性求值。n = yield rif not n:returnprint('[CONSUMER] ←← Consuming %s...' % n)time.sleep(1)r = '200 OK'def produce():# 1、首先调用c.next()启动生成器c = consumer()next(c)n = 0while n < 5:n = n + 1print('[PRODUCER] →→ Producing %s...' % n)# 2、然后,一旦生产了东西,通过c.send(n)切换到consumer执行;cr = c.send(n)# 4、produce拿到consumer处理的结果,继续生产下一条消息;print('[PRODUCER] Consumer return: %s' % cr)# 5、produce决定不生产了,通过c.close()关闭consumer,整个过程结束。 c.close()if __name__ == '__main__':start_time = time.time()# 6、整个流程无锁,由一个线程执行,produce和consumer协作完成任务,所以称为“协程”,在一个线程里协作完成。res = produce()# consumer(res)end_time = time.time()print(end_time-start_time)
串行:
def produce():n = 0res = []while n < 5:n = n + 1print('[PRODUCER] →→ Producing %s...' % n)res.append(n)return resdef consumer(res):passif __name__ == '__main__':start_time = time.time()# 6、整个流程无锁,由一个线程执行,produce和consumer协作完成任务,所以称为“协程”,在一个线程里协作完成。res = produce()consumer(res)end_time = time.time()print(end_time-start_time)
greenlet模块,方便切换,但遇到IO时,不会自动切换到其他任务
from greenlet import greenletdef eat(name):print('%s is eating 1'%name)gr2.switch('zhanwu')print('%s is eating 2' % name)gr2.switch()def play(name):print('%s is playing 1' % name)gr1.switch()print('%s is playing 2' % name)gr1 = greenlet(eat) gr2 = greenlet(play) gr1.switch('egon') #切换的时候传参
gevent模块,异步提交任务,遇到IO时可实现自动切换。
异步提交任务后,主线程结束的话,会导致子线程任务完不成,通过sleep或join实现主线程不死直到子线程运行结束。
from gevent import monkey monkey.patch_all() #将下面的阻塞操作变为非阻塞操作,这是用gevent必须的
def eat(name):print('%s is eating 1'%name)gevent.sleep(3)print('%s is eating 2' % name)def play(name):print('%s is playing 1' % name)gevent.sleep(4)print('%s is playing 2' % name)gevent.joinall([gevent.spawn(eat,'egon'),gevent.spawn(play,'egon')] )
基于gevent实现单线程下的并发。
如果开多个进程,每个进程里开多个线程,每个线程里再开协程,会大大提升效率。server端 from gevent import monkey,spawn;monkey.patch_all() from socket import *def talk(conn):while True:try:data = conn.recv(1024)if not data: breakconn.send(data.upper())except ConnectionResetError:breakconn.close()def server(ip,port): # 来一个客户端,起一个connserver = socket(AF_INET, SOCK_STREAM)server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)server.bind((ip, port))server.listen(5)while True:conn,addr = server.accept()spawn(talk,conn)server.close()if __name__ == '__main__':g = spawn(server,'127.0.0.1',8087)g.join()client端: from socket import * from threading import Thread,currentThread def client():client = socket(AF_INET, SOCK_STREAM)client.connect(('127.0.0.1',8087))while True:client.send(('%s say hello'%currentThread().getName()).encode('utf8'))data = client.recv(1024)print(data.decode('utf-8'))if __name__ == '__main__':for i in range(500):t = Thread(target=client)t.start()
转载于:https://www.cnblogs.com/stin/p/8549051.html
Python 之协程相关推荐
- 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协程的区别
进程.线程和协程 进程的定义: 进程,是计算机中已运行程序的实体.程序本身只是指令.数据及其组织形式的描述,进程才是程序的真正运行实例. 线程的定义: 操作系统能够进行运算调度的最小单位.它被包含在进 ...
- Python 的协程库 greenlet 和 gevent
greenlet 官方文档:https://greenlet.readthedocs.io/en/latest/ From:https://www.jianshu.com/u/3ab212f28d91 ...
- Python 的协程
前言 最近在看部分Python源码时, 发现了async 这个关键字. 查了一下发现了Python中的协程. 协程这玩意, 在GO中我用过啊, 简单说, 就是一个轻量级的线程嘛, 由语言自己来实现不同 ...
- 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】【入门篇】十二、Python中协程
目录 十二.Python中协程 12.1 协程的定义 12.2 协程 12.3 协程池 12.4 总结 十二.Python中协程 12.1 协程的定义 协程(Coroutine):是一种比线程更加轻量 ...
最新文章
- Trust is the most important thing to the team!
- Kubernetes中分布式存储Rook-Ceph的使用:一个ASP.NET Core MVC的案例
- 正确设置JUnit测试名称
- 剪切文件_lammps模拟带缺陷镍板剪切变形(in文件及注释)
- 23种设计模式之工厂方法模式
- java input是关键字吗_java 关键字transient
- 深度学习笔记 | 第16讲:语音识别——一份简短的技术综述
- NYOJ题目37-回文字符串
- nachos操作系统初步认识
- 【Download error:TOO MANY REQUESTS】【TypeError:excepted string or buffer】
- Android虚拟AB升级流程简述及升级完整log
- 阿里平头哥发布首个产品玄铁910 但这并不是CPU
- 飓风桑迪:曼哈顿数据中心的灾难应急方案
- linux 文件系统损坏修复方式
- 搭建一个多对多的音视频通信服务
- 经典爱情诗《四月的纪念》 刘擎/王嫣、乔榛/丁建华双版朗诵
- 计算机给文件重命名快捷键,批量重命名文件 一个F2快捷键即可全部搞定
- 关于xml加载提示: Error on line 1 of document : 前言中不允许有内容
- display:none 和 visibility:hidden的区别
- R语言抓取暴风魔镜评论数据并绘制各省市购买量热力图
热门文章
- CentOS7安装Nginx及其相关
- Linux下查看进程IO工具iopp
- Java 10更新汇总,新的编译器通吃主流编程语言
- WebP图片格式,压缩提高28%
- POJ-1094 Sorting it All Out
- 阿里云产品搭建web应用梳理
- Android应用程序消息处理机制(Looper、Handler)分析(1)
- docker部署项目 dockerfile 实战 SpringBoot、flask
- Pycharm运行Scrapy报错:no active project Unknown command: crawl Use “scrapy“ to see available commands
- DeskArtes 3Data Expert Ultimate中文版