多任务协程编程
协程,又称微线程,纤程。英文名Coroutine。
协程也是一种轻量级的多任务编程技术,它可以在同一个线程中实现多个任务的切换和调度。
协程通过任务的暂停和恢复,避免了线程切换的开销并减少了锁的使用。协程常用于异步编程场景,比如网络编程和IO密集型任务。
最大的优势就是协程极高的执行效率。因为函数切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。
第二大优势就是不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。
比如:一个人在打印资料的等待过程中,又去接听了客户的电话,在接听电话的等待过程中,又整理了桌面。
Python 中可以使用第三方模块 gevent
实现进程多任务编程。
# pip install gevent
import gevent
创建协程
gevent
模块使用 spawn
类创建协程实例对象,实现协程任务的创建。
spawn(run [, args [, kwargs]])
参数说明:
run
:执行的目标任务名args
:以元组方式给执行任务传参kwargs
:以字典方式给执行任务传参
import gevent
def task():
for i in range(1,3):
print(i)
g1 = gevent.spawn(task)
g2 = gevent.spawn(task)
g3 = gevent.spawn(task)
启动进程
协程对象创建成功后,需要使用 join()
方法启动协程才会开始执行。
该方法的作用是对当前线程进行阻塞,直到协程执行结束后,继续执行当前线程。
g1.join()
g2.join()
g3.join()
print("main")
获取当前协程对象
gevent.getcurrent()
可以获取当前协程对象。
import gevent
def task():
for i in range(1,3):
print(gevent.getcurrent(), i)
g1 = gevent.spawn(task)
g2 = gevent.spawn(task)
g1.join()
g2.join()
协程组
在创建多个协程对象后,可以将多个协程对象放入一个元组或列表中,然后使用 gevent.joinall()
方法同时启动协程对象。
import gevent
def task():
for i in range(1,3):
print(gevent.getcurrent(), i)
# 使用列表推导式,生成一个有5个协程对象的列表
gs = [gevent.spawn(task) for i in range(5)]
gevent.joinall(gs)
协程切换
从前面的代码执行结果看,虽然可以执行多个协程任务,但是任务的执行过程依然是同步的。
可以通过在代码中添加 gevent.sleep()
方法模拟耗时操作,实现协程任务的切换。
注意: sleep()
方法是 gevent
模块中的,不是 time
模块中的。
import gevent
def task():
for i in range(1,3):
print(gevent.getcurrent(), i)
gevent.sleep(0.001)
# 使用列表推导式,生成一个有5个协程对象的列表
gs = [gevent.spawn(task) for i in range(5)]
gevent.joinall(gs)
协程任务函数传参
在创建协程对象的时候,为协程任务函数传递参数,可以使用两种方式为任务函数传参。
args
: 使用可变位置参数形式传参kwargs
: 使用可变关键字参数形式传参
协程的任务函数传参与进程和线程不同,协程可以和直接使用函数一样,在 spawn
方法中为任务函数传参。
import gevent
def task(n, msg):
for i in range(1,n+1):
print(gevent.getcurrent(), f"第 {i} 次输出 {msg}")
gevent.sleep(0.001)
g1 = gevent.spawn(task,5, "Python")
g2 = gevent.spawn(task, msg="Hogwarts", n=5)
g1.join()
g2.join()
协程异步
在 Python 中,Gevent 的 monkey patch 是指使用 Gevent 的模块 gevent.monkey
中的 patch_all()
等方法,来替换标准库中的一些阻塞式 I/O 操作,以实现非阻塞式的协程 I/O。
一般该方法写在程序的第一行。
from gevent import monkey
monkey.patch_all()
import gevent
import random
def task(n, msg):
for i in range(1,n+1):
print(gevent.getcurrent(), f"第 {i} 次输出 {msg}")
gevent.sleep(random.random())
g1 = gevent.spawn(task,5, "Python")
g2 = gevent.spawn(task, msg="Hogwarts", n=5)
g3 = gevent.spawn(task, n=5, msg="Hello")
gevent.joinall((g1,g2,g3))
在 Python 3.10 版本中,Gevent 的 monkey patch 功能在某些情况下可能无效。这是因为在 Python 3.10 中引入了 asyncio
的新的事件循环机制,与 Gevent 的事件循环有所不同,导致 monkey patch 在有些情况下失效。
Gevent 官方还没有正式发布兼容 Python 3.10 版本的版本,因此在 Python 3.10 中使用 monkey.patch_all()
方法可能无法正常实现非阻塞的协程 I/O。
为了解决这个问题,你可以考虑使用 Python 3.10 引入的 asyncio 模块来进行异步编程。
asyncio 提供了原生的协程和事件循环,可以实现高效的异步操作。
在测试领域,技术的提升固然至关重要,然而,同样不可忽视的是测试管理软技能的必要性。拥有卓越的测试技术能力是基石,但在现代软件开发环境中,仅凭技术本身难以应对项目的复杂性和团队协作的挑战。测试管理软技能的提升可以为技术高工打开更广阔的发展空间。
首先,测试管理能力使你能够更好地规划、组织和执行测试策略。通过学习测试管理,你将能够更有效地制定测试计划、分配资源,并合理安排测试活动,从而提高项目的整体效率。
其次,软技能的提升将增强你在团队中的领导力和沟通能力。良好的测试管理者不仅能够理解技术细节,还能够与不同职能团队有效沟通,推动团队朝着共同的目标前进。这种全面的素养在职业发展中至关重要,有助于建立良好的团队协作氛围。
最后,测试管理软技能的提升有助于更好地理解业务需求和用户期望。通过深入了解项目的背景和目标,你将能够更有针对性地设计和执行测试,确保产品不仅在技术上优秀,还能够满足用户的期望,提升整体用户体验。
因此,作为技术高工,将精力投入到测试管理软技能的学习和提升中,不仅有助于个人职业发展,也将为团队和项目的成功贡献更大的价值。
以上就是“Python多任务协程“构建高性能应用的隐秘武器!”的全部内容,希望对你有所帮助。
关于Python技术储备
学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!
一、Python所有方向的学习路线
Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
二、Python必备开发工具
三、Python视频合集
观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
四、实战案例
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
五、Python练习题
检查学习结果。
六、面试资料
我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
最后祝大家天天进步!!
上面这份完整版的Python全套学习资料已经上传至CSDN官方,朋友如果需要可以直接微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】。