深入理解Python中的并发与异步的结合使用

news2024/11/23 21:07:09

​ 在上一篇文章中,我们讨论了异步编程中的性能优化技巧,并简单介绍了triocurio库。今天,我们将深入探讨如何将并发编程与异步编程结合使用,并详细讲解如何利用triocurio库优化异步编程中的性能。

文章目录

        • 并发与异步编程的区别与联系
        • 并发编程与异步编程的优缺点
          • 并发编程
          • 异步编程
        • 如何在同一个程序中同时使用 `threading`、`multiprocessing` 和 `asyncio`
          • 使用 `threading` 和 `asyncio`
        • 深入使用 `trio` 库
          • 基本使用
          • 高级功能:取消与超时
        • 深入使用 `curio` 库
          • 基本使用
          • 高级功能:任务取消与超时
      • 性能优化技巧
      • 结语

并发与异步编程的区别与联系

并发编程和异步编程都是处理多任务的有效手段,但它们的实现方式和适用场景有所不同:

  • 并发编程:通过线程或进程来同时执行多个任务,适用于CPU密集型任务;
  • 异步编程:通过事件循环和协程来调度任务,适用于I/O密集型任务。

结合使用并发和异步编程,可以同时处理CPU密集型和I/O密集型任务,提升程序整体性能。

并发编程与异步编程的优缺点
并发编程
  • 优点
    • 可以充分利用多核CPU的优势,提高程序的执行效率;
    • 适用于需要大量计算的任务,例如数据处理、图像处理等。
  • 缺点
    • 线程和进程的管理和调度较为复杂,需要处理同步、锁等问题;
    • 创建和销毁线程或进程会有一定的开销。
异步编程
  • 优点
    • 适用于I/O密集型任务,可以在等待I/O操作完成时执行其他任务,提高资源利用率;
    • 代码更加简洁,逻辑清晰。
  • 缺点
    • 仅能在单线程中运行,不能利用多核CPU的优势;
    • 对于CPU密集型任务效果不佳。
如何在同一个程序中同时使用 threadingmultiprocessingasyncio

在同一个程序中,我们可以利用 threadingmultiprocessing 提供并发能力,同时使用 asyncio 实现异步I/O操作:

使用 threadingasyncio
import asyncio
import threading

async def async_task():
    print("Starting async task")
    await asyncio.sleep(2)
    print("Async task completed")

def sync_task(loop):
    print("Starting sync task")
    loop.run_until_complete(async_task())
    print("Sync task completed")

loop = asyncio.get_event_loop()
thread = threading.Thread(target=sync_task, args=(loop,))
thread.start()
thread.join()

使用 multiprocessingasyncio

import asyncio
import multiprocessing

async def async_task():
    print("Starting async task")
    await asyncio.sleep(2)
    print("Async task completed")

def sync_task():
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_until_complete(async_task())

if __name__ == "__main__":
    process = multiprocessing.Process(target=sync_task)
    process.start()
    process.join()
深入使用 trio

trio对异步编程提供了更友好的API,以及更加健壮的错误处理机制;它简化了异步编程的许多复杂性,特别是对于需要多个并发任务的场景:

基本使用
import trio
import asks

async def fetch(url):
    response = await asks.get(url)
    return response.text

async def main():
    urls = ['http://example.com', 'http://example.org', 'http://example.net']
    async with trio.open_nursery() as nursery:
        for url in urls:
            nursery.start_soon(fetch, url)

trio.run(main)
高级功能:取消与超时

trio中,可以轻松地对任务进行取消和超时操作:

import trio

async def long_running_task():
    try:
        print("Task started")
        await trio.sleep(10)
        print("Task completed")
    except trio.Cancelled:
        print("Task was cancelled")

async def main():
    async with trio.open_nursery() as nursery:
        nursery.start_soon(long_running_task)
        await trio.sleep(5)
        nursery.cancel_scope.cancel()

trio.run(main)

异常处理与重试机制

import trio
import asks

async def fetch_with_retry(url, retries=3):
    for attempt in range(retries):
        try:
            response = await asks.get(url)
            return response.text
        except Exception as e:
            print(f"Attempt {attempt + 1} failed: {e}")
            await trio.sleep(2)
    raise Exception(f"Failed to fetch {url} after {retries} attempts")

async def main():
    urls = ['http://example.com', 'http://example.org', 'http://example.net']
    async with trio.open_nursery() as nursery:
        for url in urls:
            nursery.start_soon(fetch_with_retry, url)

trio.run(main)
深入使用 curio

curio 是另一个异步编程库,主要强调简单性和高性能,适用于需要低延迟和高吞吐量的场景:

基本使用
import curio
import httpx

async def fetch(url):
    async with httpx.AsyncClient() as client:
        response = await client.get(url)
        return response.text

async def main():
    urls = ['http://example.com', 'http://example.org', 'http://example.net']
    tasks = [fetch(url) for url in urls]
    results = await curio.gather(tasks)
    for result in results:
        print(result[:100])

if __name__ == "__main__":
    curio.run(main)
高级功能:任务取消与超时

curio 和trio一样提供了强大的任务管理功能,其中也包括对任务取消和超时操作的处理:

import curio

async def long_running_task():
    try:
        print("Task started")
        await curio.sleep(10)
        print("Task completed")
    except curio.CancelledError:
        print("Task was cancelled")

async def main():
    task = await curio.spawn(long_running_task)
    await curio.sleep(5)
    await task.cancel()

if __name__ == "__main__":
    curio.run(main)

使用信号与事件进行任务同步

import curio![](https://files.mdnice.com/user/68804/a9f7fe95-2fc1-4c87-963a-cdbf8c34108b.jpg)


async def producer(event):
    print("Producer sleeping")
    await curio.sleep(5)
    print("Producer setting event")
    await event.set()

async def consumer(event):
    print("Consumer waiting for event")
    await event.wait()
    print("Consumer got event")

async def main():
    event = curio.Event()
    await curio.gather(producer(event), consumer(event))

if __name__ == "__main__":
    curio.run(main)

性能优化技巧

通过结合并发和异步编程技术,以及使用triocurio库,我们可以在处理大量I/O密集型任务时获得显著的性能提升,以下是我在工作中常用的一些性能优化技巧:

  1. 限制并发请求数量:使用信号量(semaphore)限制同时进行的请求数量,防止过多的请求导致系统资源枯竭;
  2. 分块处理任务:将任务划分为多个块,分别进行处理,避免一次性处理大量任务导致的性能问题;
  3. 使用连接池:复用连接,减少连接建立和销毁的开销;
  4. 合理设置超时时间:为每个请求设置合理的超时时间,防止由于某些请求超时导致整个任务的延迟;
  5. 异步I/O操作:尽量使用异步I/O操作,避免阻塞主线程。

结语

通过本文的介绍,我们深入学习了如何将并发编程与异步编程结合使用,以最大化程序的性能和效率。结合使用 threadingmultiprocessingasyncio 可以同时处理CPU密集型和I/O密集型任务,提升程序整体性能,希望这些技巧能帮助你在实际项目中编写出高效、稳定的代码!
如果你对计算机相关技术有更多的兴趣,想要持续的探索,请关注我的公众号哟!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1850088.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

鸿蒙HarmonyOS NEXT角落里的知识:ArkTS高性能编程实践

概述 本文主要提供应用性能敏感场景下的高性能编程的相关建议,助力开发者开发出高性能的应用。高性能编程实践,是在开发过程中逐步总结出来的一些高性能的写法和建议,在业务功能实现过程中,我们要同步思考并理解高性能写法的原理…

AMSR/ADEOS-II L1A Raw Observation Counts V003地球表面和大气微波辐射的详细观测数据

AMSR/ADEOS-II L1A Raw Observation Counts V003 简介 AMSR/ADEOS-II L1A Raw Observation Counts V003数据是由日本航空航天研究开发机构(JAXA)的AMSR (Advanced Microwave Scanning Radiometer)仪器收集的一组原始观测计数数据。这些数据是从ADEOS-I…

2024年高压电工证考试题库及高压电工试题解析

题库来源:安全生产模拟考试一点通公众号小程序 2024年高压电工证考试题库及高压电工试题解析是安全生产模拟考试一点通结合(安监局)特种作业人员操作证考试大纲和(质检局)特种设备作业人员上岗证考试大纲随机出的高压…

第2章 Android应用的界面编程

🌈个人主页:小新_- 🎈个人座右铭:“成功者不是从不失败的人,而是从不放弃的人!”🎈 🎁欢迎各位→点赞👍 收藏⭐️ 留言📝 🏆所属专栏&#xff1…

高通安卓12-Input子系统

1.Input输入子系统架构 Input Driver(Input设备驱动层)->Input core(输入子系统核心层)->Event handler(事件处理层)->User space(用户空间) 2.getevent获取Input事件的用法 getevent 指令用于获取android系统中 input 输入事件,比如获取按键上报信息、获…

04_FFmpeg常用API及内存模型

【说明】课程学习地址:https://ke.qq.com/course/468797 FFmpeg内存模型 FFmpeg内存模型 int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt); int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);问题(数据的申请和释放): …

Python高效内存访问,memoryview这个神器你值得拥有!

目录 1、初识memoryview 🌀 1.1 memoryview基础介绍 1.2 为何使用memoryview优化内存访问 1.3 创建memoryview对象实战 示例1:基于bytes创建memoryview 示例2:修改memoryview中的数据 示例3:memoryview与切片 2、深入理解memoryview操作 🔄 2.1 访问与修改数据…

【Java】已解决java.nio.channels.FileLockInterruptionException异常

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例 已解决java.nio.channels.FileLockInterruptionException异常 在Java NIO(New I/O)中,java.nio.channels.FileLockInterruptionException是一个特殊的异常&am…

tedsign vue3 web-端框架中封装一个验证码组件 以及对应node 接口逻辑说明

一个这样的组件 我直接上代码了 <template><t-loading size"small" :loading"loading" show-overlay><div class"container" click"refresh"><div v-if"svg" class"svg" v-html"svg&…

VUE3脚手架工具cli配置搭建及创建VUE工程

1、VUE的脚手架工具(CLI&#xff09; 开发大型vue的时候&#xff0c;不能通过html编写一个大型的项目&#xff0c;这个时候需要用到vue的脚手架工具 通过vue的脚手架&#xff0c;可以快速的生成vue工程 1.1、安装nodejs和npm 【下载nodejs】 https://nodejs.org/en 【安装…

高通安卓12-安卓系统定制2

将开机动画打包到system.img里面 在目录device->qcom下面 有lito和qssi两个文件夹 现在通过QSSI的方式创建开机动画&#xff0c;LITO方式是一样的 首先加入自己的开机动画&#xff0c;制作过程看前面的部分 打开qssi.mk文件&#xff0c;在文件的最后加入内容 PRODUCT_CO…

python爬虫学习笔记一(基本概念urllib基础)

学习资料&#xff1a;尚硅谷_爬虫 学习环境: pycharm 一.爬虫基本概念 爬虫定义 > 解释1&#xff1a;通过程序&#xff0c;根据URL进行爬取网页&#xff0c;获取有用信息 > 解释2&#xff1a;使用程序模拟浏览器&#xff0c;向服务器发送请求&#xff0c;获取相应信息…

某程序员:30岁了,老婆管钱,背着我买了50万股票,亏了20w,强制她清仓后又买了36万

“辛辛苦苦攒了几年钱&#xff0c;本想买房买车&#xff0c;结果全被老婆炒股亏掉了&#xff01;” 近日&#xff0c;一位30岁的程序员大哥在网上吐苦水&#xff0c;引发了网友们的热议。 这位程序员大哥和妻子结婚后&#xff0c;一直秉持着“男主外&#xff0c;女主内”的传统…

C++——位图的介绍和使用

位图的介绍 位图的引入 给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一个数是否在这40亿个数中&#xff1f; 要判断一个数是否在某一堆数中&#xff0c;我们可能会想到如下方法&#xff1a; 将这一堆数进行排序&#xff0c…

VBA学习(16):工作表事件示例:输入数据后锁定单元格

在工作表单元格中输入数据后&#xff0c;该单元格就被锁定&#xff0c;不能再编辑。 打开VBE&#xff0c;在工程资源管理器中双击该工作表名称打开其代码模块&#xff0c;在其中输入下面的代码&#xff1a; 假设整个工作表的LockedFalse Private Sub Worksheet_Change(ByVal …

【文献及模型、制图分享】1985-2015年美国坦帕湾流域土地开发利用强度时空变化分析

公众号新功能 目前公众号新增以下等功能 1、处理GIS出图、Python制图、区位图、土地利用现状图、土地利用动态度和重心迁移图等等 2、核密度分析、网络od分析、地形分析、空间分析等等 3、地理加权回归、地理探测器、生态环境质量指数、地理加权回归模型影响因素分析、计算…

顶顶通呼叫中心中间件-机器人测试流程(mod_cti基于FreeSWITCH)

感兴趣的话可以点后面链接添加联系方式顶顶通小孙 一、打开ccadmin-web并且创建分机 1、登录ccadmin-web 登录地址&#xff1a;http://ddcti.com:88 登录之后根据下图去登录ccadmin-web系统。 2、创建分机 点击呼叫中心 -> 点击分机设置 -> 点击新增&#xff0c;点击…

超级管道,品质非凡——钢塑复合管

钢塑复合管&#xff0c;是一种新型的复合管材&#xff0c;又叫涂塑钢管&#xff0c;涂塑钢管有内涂塑钢管&#xff0c;外涂塑钢管&#xff0c;内外涂塑钢管&#xff0c;外镀锌内涂塑钢管&#xff0c;外3pe防腐内涂塑钢管等。 它结合了钢管和塑料管的优点&#xff0c;具有高强度…

LATR 算法解读

文章目录 1. 论文2. 环境安装3. 代码解读3. 1 初始化 lane query3.1.1 SparseInsDecoder3.1.2 loss 计算3.1.3 初始化instance query3.2 ref points 的生成3.3 lane query 和feats进行attention3.3.1 self attn3.3.1 cross attn4. 参考1. 论文 2. 环境安装 146 [2024-06-20 10…

用自己的数据集训练TimeSformer并转ONNX用c++推理

用自己的数据集训练TimeSformer并转ONNX用c++推理 文章目录 用自己的数据集训练TimeSformer并转ONNX用c++推理下载安装TimeSformer创建分类文件夹创建数据集修改训练配置运行脚本开始训练测试模型模型转为onnx测试一下生成的onnx模型转为用c++推理下载安装TimeSformer TimeSfo…