多线程并发、包括线程池,是操作系统控制的并发。如果是单线程,可以通过协程实现单线程下的并发。

协程 又称微线程,是一种用户态的轻量级线程,由用户程序自己控制调度。

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 之协程相关推荐

  1. python gevent 协程

    python gevent 协程 def func1():print("fun1开始运行")gevent.sleep(2) # 内部函数实现io操作print("func ...

  2. Python基础入门教程:使用 Python 3 协程快速获得一个代理池

    Python基础入门教程:使用 Python 3 协程快速获得一个代理池 前言 在执行 IO 密集型任务的时候,程序会因为等待 IO 而阻塞.比如我们使用 requests 库来进行网络爬虫请求的话, ...

  3. python中协程与函数的区别_深入浅析python 协程与go协程的区别

    进程.线程和协程 进程的定义: 进程,是计算机中已运行程序的实体.程序本身只是指令.数据及其组织形式的描述,进程才是程序的真正运行实例. 线程的定义: 操作系统能够进行运算调度的最小单位.它被包含在进 ...

  4. python中协程与函数的区别_python 协程与go协程的区别

    进程.线程和协程 进程的定义: 进程,是计算机中已运行程序的实体.程序本身只是指令.数据及其组织形式的描述,进程才是程序的真正运行实例. 线程的定义: 操作系统能够进行运算调度的最小单位.它被包含在进 ...

  5. Python 的协程库 greenlet 和 gevent

    greenlet 官方文档:https://greenlet.readthedocs.io/en/latest/ From:https://www.jianshu.com/u/3ab212f28d91 ...

  6. Python 的协程

    前言 最近在看部分Python源码时, 发现了async 这个关键字. 查了一下发现了Python中的协程. 协程这玩意, 在GO中我用过啊, 简单说, 就是一个轻量级的线程嘛, 由语言自己来实现不同 ...

  7. python3 协程 写法_理解Python的协程(Coroutine)

    由于GIL的存在,导致Python多线程性能甚至比单线程更糟. GIL: 全局解释器锁(英语:Global Interpreter Lock,缩写GIL),是计算机程序设计语言解释器用于同步线程的一种 ...

  8. python携程使用_简单了解python gevent 协程使用及作用

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

  9. python 异步协程爬虫-半次元图片

    python 异步协程爬虫-半次元图片 1. 页面分析 2.代码大体构思 3.源码分析 3.1 完成效果 4.异步协程的优势 5.难点分析 6.可扩展性 欢迎私信或评论区交流 爬取网址 : https ...

  10. 【Python】【入门篇】十二、Python中协程

    目录 十二.Python中协程 12.1 协程的定义 12.2 协程 12.3 协程池 12.4 总结 十二.Python中协程 12.1 协程的定义 协程(Coroutine):是一种比线程更加轻量 ...

最新文章

  1. Trust is the most important thing to the team!
  2. Kubernetes中分布式存储Rook-Ceph的使用:一个ASP.NET Core MVC的案例
  3. 正确设置JUnit测试名称
  4. 剪切文件_lammps模拟带缺陷镍板剪切变形(in文件及注释)
  5. 23种设计模式之工厂方法模式
  6. java input是关键字吗_java 关键字transient
  7. 深度学习笔记 | 第16讲:语音识别——一份简短的技术综述
  8. NYOJ题目37-回文字符串
  9. nachos操作系统初步认识
  10. 【Download error:TOO MANY REQUESTS】【TypeError:excepted string or buffer】
  11. Android虚拟AB升级流程简述及升级完整log
  12. 阿里平头哥发布首个产品玄铁910 但这并不是CPU
  13. 飓风桑迪:曼哈顿数据中心的灾难应急方案
  14. linux 文件系统损坏修复方式
  15. 搭建一个多对多的音视频通信服务
  16. 经典爱情诗《四月的纪念》 刘擎/王嫣、乔榛/丁建华双版朗诵
  17. 计算机给文件重命名快捷键,批量重命名文件 一个F2快捷键即可全部搞定
  18. 关于xml加载提示: Error on line 1 of document : 前言中不允许有内容
  19. display:none 和 visibility:hidden的区别
  20. R语言抓取暴风魔镜评论数据并绘制各省市购买量热力图

热门文章

  1. CentOS7安装Nginx及其相关
  2. Linux下查看进程IO工具iopp
  3. Java 10更新汇总,新的编译器通吃主流编程语言
  4. WebP图片格式,压缩提高28%
  5. POJ-1094 Sorting it All Out
  6. 阿里云产品搭建web应用梳理
  7. Android应用程序消息处理机制(Looper、Handler)分析(1)
  8. docker部署项目 dockerfile 实战 SpringBoot、flask
  9. Pycharm运行Scrapy报错:no active project Unknown command: crawl Use “scrapy“ to see available commands
  10. DeskArtes 3Data Expert Ultimate中文版