Python多任务协程:编写高性能应用的秘密武器

简介: Python多任务协程:编写高性能应用的秘密武器

image.png

测试管理班是专门面向测试与质量管理人员的一门课程,通过提升从业人员的团队管理、项目管理、绩效管理、沟通管理等方面的能力,使测试管理人员可以更好的带领团队、项目以及公司获得更快的成长。提供 1v1 私教指导,BAT 级别的测试管理大咖量身打造职业规划。

多任务协程编程

协程,又称微线程,纤程。英文名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 提供了原生的协程和事件循环,可以实现高效的异步操作。

相关文章
|
4天前
|
Java Serverless 应用服务中间件
Serverless 应用引擎操作报错合集之部署python项目时,构建过程报错,怎么解决
Serverless 应用引擎(SAE)是阿里云提供的Serverless PaaS平台,支持Spring Cloud、Dubbo、HSF等主流微服务框架,简化应用的部署、运维和弹性伸缩。在使用SAE过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
|
1天前
|
机器人 测试技术 持续交付
Python进行自动化测试测试框架的选择与应用
【6月更文挑战第9天】本文介绍了Python自动化测试的重要性及选择测试框架的考量因素,如功能丰富性、易用性、灵活性和集成性。文中列举了常用的Python测试框架,包括unittest、pytest、nose2和Robot Framework,并提供了使用pytest进行单元测试的示例代码。此外,还展示了如何使用Robot Framework进行验收测试和Web UI测试。选择合适的测试框架对提升测试效率和软件质量至关重要,团队应根据项目需求、社区支持、集成性和学习曲线等因素进行选择。通过不断学习和实践,可以优化自动化测试流程,确保软件的稳定性和可靠性。
6 0
|
2天前
|
机器学习/深度学习 存储 自然语言处理
惊艳!老司机熬夜总结的Python高性能编程,高效、稳定、快速!
Python 语言是一种脚本语言,其应用领域非常广泛,包括数据分析、自然语言处理机器学习、科学计算、推荐系统构建等。 能够轻松实现和代码跑得够快之间的取舍却是一个世人皆知且令人惋惜的现象而这个问题其实是可以解决的。 有些人想要让顺序执行的过程跑得更快。有些人需要利用多核架构、集群,或者图形处理单元的优势来解决他们的问题。有些人需要可伸缩系统在保证可靠性的前提下酌情或根据资金多少处理更多或更少的工作。有些人意识到他们的编程技巧,通常是来自其他语言,可能不如别人的自然。
|
4天前
|
存储 Serverless 数据库
Serverless 应用引擎产品使用合集之在Python中,如何实现SSE
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
|
5天前
|
缓存 开发者 Python
Python中的装饰器应用及性能优化
本文探讨了Python中装饰器的作用以及如何应用装饰器来提高代码的可读性和灵活性。同时,我们还将介绍一些性能优化的技巧,帮助开发者更好地理解和利用装饰器来提升Python程序的执行效率。
|
5天前
|
API 开发者 UED
Python在游戏开发中的应用?
【6月更文挑战第10天】Python在游戏开发中的应用?
5 1
|
5天前
|
人工智能 数据可视化 开发者
|
5天前
|
存储 算法 搜索推荐
掌握区间合并:解决实际问题的算法策略和应用案例【python LeetCode题目56】
掌握区间合并:解决实际问题的算法策略和应用案例【python LeetCode题目56】
|
5天前
|
存储 算法 安全
LeetCode 题目 49:字母异位词分组 5种算法实现与典型应用案例【python】
LeetCode 题目 49:字母异位词分组 5种算法实现与典型应用案例【python】
|
5天前
|
存储 算法 数据可视化
【贪心算法经典应用】活动选择详解 python
【贪心算法经典应用】活动选择详解 python