协程
一、协程的基本概念:是一个微线程,不会产生cpu的开销,有自己的寄存器。
1、yield
(1)、在自定义函数中使用yield表明自定义函数为生成器
(2)、生成器常用的方法有:
A、generator.__next__():在上一次yield的位置继续执行
B、generator.send():在上一次函数中yield的位置继续执行,并且传递参数给yield
2、yield的例子

def producer(): print('\033[1;31m[Producer]\033[0m开始生产包子了') c1.__next__() c2.__next__() n = 0 while n < 5: n += 1 print('\033[1;31m[Producer]\033[0m生产第%s个包子' % n) c1.send(n) c2.send(n) def consumer(name): print('\033[1;31m%s\033[0m开始吃包子了!' % name) while True: baozi = yield print('%s要吃第%s个包子' % (name, baozi)) c1 = consumer('Treelight') c2 = consumer('Alex') p = producer()
3、在协程中手动切换

from greenlet import greenlet def run1(): print('First time in run1') g2.switch() print('Second time in run1') g2.switch() def run2(): print('First time in run2') g1.switch() print('Second time in run2') if __name__ == '__main__': g1 = greenlet(run=run1) g2 = greenlet(run=run2) g1.switch()
(1)、协程中什么时候产生上下文切换:产生IO时
(2)用法:
A、定义实例 g1 = greelet(run=<func_name>)
B、切换到g1:g1.swich()
4、自动切换,例子:

import gevent def run1(): print('in the run1') gevent.sleep(2) # 模拟IO print('in the run1 again') def run2(): print('in the run2') gevent.sleep(1) # 模拟IO print('in the run2 again') def run3(): print('in the run3') gevent.sleep(0) # 模拟IO print('in the run3 again') if __name__ == '__main__': gevent.joinall([ # 需使用列表 gevent.spawn(run1), # 生成 gevent.spawn(run2), gevent.spawn(run3) ]) # 在gevent的joinall方法中需使用列表
(1)、gevent.sleep():模拟IO
(2)、gevent.joinall([gevent.spawn(<fun_name>)。。。。]) 需使用列表,生成。
二、协程的基本案例
1、爬虫(注意:需要使用monkey模块,调用monkey.patch_all,使得gevent能识别程序中的IO)

import gevent from urllib import request import time from gevent import monkey monkey.patch_all() # 打补丁,使得gevent能识别此程序中产生的IO,从此产生上下文的切换 def get_url_data(url): print('获取%s的数据' % url) data = request.urlopen(url).read() print('网页%s的大小:%s' % (url, len(data))) start_time = time.time() url_list = ['https://www.python.org/', 'https://www.yahoo.com/', 'https://github.com' ] for url in url_list: get_url_data(url) print('同步获取网页的时间是:', (time.time() - start_time)) print('\n\n') start_time = time.time() gevent.joinall([ gevent.spawn(get_url_data, 'https://www.python.org/'), gevent.spawn(get_url_data, 'https://www.yahoo.com/'), gevent.spawn(get_url_data, 'https://github.com/') ]) print('异步获取网页的时间是:', (time.time() - start_time))
2、在socket上实现了并发

import gevent import socket from gevent import monkey monkey.patch_all() def server(port): svr= socket.socket() svr.bind(('localhost', port)) svr.listen() while True: conn, addr = svr.accept() gevent.spawn(handle_request, conn) def handle_request(conn): while True: try: data = conn.recv(1024) conn.send(data) except ConnectionResetError: print('客户端已断开') break server(9999)

import socket client = socket.socket() client.connect(('localhost', 9999)) while True: msg = input('>>:').strip() client.send(msg.encode('utf-8')) print(client.recv(1024))
三、协程实现的基本原理
协程当一遇到IO操作就会切换,IO操作完就会回来。那如何监测IO操作呢?就是通过事件驱动的方式。当一个事件发生时,就会注册一个事件,放到一个队列,然后就产生IO操作,协程就把IO操作交给了操作系统,同时协程还声明了一个回调函数给操作系统,以便通知协程IO已经操作完毕。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」