首页 > 编程语言 >【python学习】Asyncio库的真正力量:如何用Python编写高效并发程序

【python学习】Asyncio库的真正力量:如何用Python编写高效并发程序

时间:2024-08-17 10:55:20浏览次数:14  
标签:task Python await python async main 并发程序 def asyncio

目标读者群体及文章解决的问题

这篇文章适合对Python编程有一定了解的开发者,尤其是希望深入理解并掌握异步编程的读者。通过对asyncio库的全面解析,我们将结合2023年环法冠军温格高的夺冠故事,帮助你掌握如何在Python中使用异步编程处理复杂的并发任务,避免常见的错误,并提高代码的执行效率。

Asyncio与环法:优化与掌控的艺术

温格高在环法比赛中的胜利不仅源于他的体能和技巧,更重要的是他对时间和资源的高效掌控。asyncio库在Python中扮演了类似的角色,通过精细的任务调度与优化,让你能够像温格高一样,在并发编程中游刃有余。

深入理解Asyncio的核心概念

事件循环 (Event Loop)

事件循环是asyncio的核心。它负责调度和运行所有的协程任务,类似于温格高在比赛中调度体能和战术的整体策略。我们可以手动控制事件循环,以便更灵活地管理协程任务。

import asyncio

async def simple_task():
    print("Task started")
    await asyncio.sleep(1)
    print("Task completed")

# 手动控制事件循环
loop = asyncio.get_event_loop()
loop.run_until_complete(simple_task())
loop.close()

输出结果:

Task started
Task completed

这里,我们手动启动和关闭了事件循环,这使得我们可以更灵活地管理多个协程任务,特别是在更复杂的并发场景中。

任务 (Tasks) 与 Futures

任务(Task)是运行协程的高级别对象,它允许你并发执行多个协程,并能够在它们之间共享结果。Futures是用来表示某个操作将在未来完成的对象。

async def fetch_data(source):
    await asyncio.sleep(2)
    return f"Data from {source}"

async def main():
    task1 = asyncio.create_task(fetch_data("Source A"))
    task2 = asyncio.create_task(fetch_data("Source B"))

    # 等待所有任务完成
    result1 = await task1
    result2 = await task2

    print(result1)
    print(result2)

asyncio.run(main())

输出结果:

Data from Source A
Data from Source B

在这里,asyncio.create_task将协程包装为任务对象,并允许我们并发执行多个任务,就像温格高在比赛中同时控制多个战术元素一样。

错误处理与取消任务

在复杂的并发任务中,错误处理至关重要。如果温格高在比赛中忽视了细节上的错误,他可能无法完成比赛。同样地,在asyncio中,我们需要对异常进行捕捉和处理,以确保任务的顺利执行。

async def faulty_task():
    await asyncio.sleep(1)
    raise ValueError("Something went wrong")

async def main():
    task = asyncio.create_task(faulty_task())

    try:
        await task
    except ValueError as e:
        print(f"Caught an error: {e}")

asyncio.run(main())

输出结果:

Caught an error: Something went wrong

此外,在某些情况下,我们可能需要取消一个任务,就像温格高在比赛中可能需要放弃某个策略一样。取消任务可以通过调用task.cancel()来实现。

async def long_running_task():
    try:
        await asyncio.sleep(10)
    except asyncio.CancelledError:
        print("Task was cancelled")
        raise

async def main():
    task = asyncio.create_task(long_running_task())
    await asyncio.sleep(1)  # 等待1秒后取消任务
    task.cancel()

    try:
        await task
    except asyncio.CancelledError:
        print("Handled task cancellation")

asyncio.run(main())

输出结果:

Task was cancelled
Handled task cancellation
异步队列 (asyncio.Queue)

异步队列允许我们在多个协程之间安全地传递数据,就像温格高的团队在比赛中高效地传递信息和资源一样。

async def producer(queue):
    for i in range(3):
        await asyncio.sleep(1)
        await queue.put(f"Item {i}")
        print(f"Produced: Item {i}")

async def consumer(queue):
    while True:
        item = await queue.get()
        if item is None:
            break
        print(f"Consumed: {item}")
        queue.task_done()

async def main():
    queue = asyncio.Queue()
    await asyncio.gather(producer(queue), consumer(queue))

asyncio.run(main())

输出结果:

Produced: Item 0
Consumed: Item 0
Produced: Item 1
Consumed: Item 1
Produced: Item 2
Consumed: Item 2

这里,生产者和消费者协程通过队列进行通信,确保任务的协调和同步。

小技巧与常见陷阱

跨平台兼容性

asyncio在不同操作系统上的行为可能会有所不同,特别是在Windows和Unix系统之间。例如,在Windows上,默认的事件循环是ProactorEventLoop,它在处理文件I/O时可能表现得不同于Unix的SelectorEventLoop

阻塞调用

在异步代码中使用阻塞调用会导致性能瓶颈,就像温格高在比赛中遇到意外阻碍一样。为了避免这种情况,应该使用asyncio.to_thread来将阻塞函数转移到独立线程中运行。

import time

async def blocking_function():
    print("Blocking call in progress...")
    time.sleep(2)
    print("Blocking call completed")

async def main():
    await asyncio.to_thread(blocking_function)

asyncio.run(main())

输出结果:

Blocking call in progress...
Blocking call completed

通过asyncio.to_thread,我们可以在异步代码中安全地执行阻塞操作,不影响事件循环的运行。

调试与日志

asyncio提供了调试模式,通过设置环境变量或使用asyncio.run中的debug=True参数,可以帮助我们跟踪协程的执行状态,捕捉潜在的问题。

import asyncio

async def faulty_task():
    await asyncio.sleep(1)
    1 / 0  # 故意触发错误

async def main():
    await asyncio.gather(faulty_task())

asyncio.run(main(), debug=True)

在调试模式下,错误信息会更加详细,有助于我们快速定位问题。

参考资料

这篇文章通过结合温格高的比赛策略,深入解析了asyncio的各种功能和常见陷阱,希望能够帮助你在实际项目中高效使用asyncio,避免常见错误,并最终掌握异步编程的核心技能。

标签:task,Python,await,python,async,main,并发程序,def,asyncio
From: https://blog.csdn.net/m0_54007171/article/details/141277320

相关文章

  • Python解释器如何下载+如何安装+配置环境+踩坑 一文搞定【保姆级图文教程】
    如果你要学Python,那么第一件事情就是先去安装。因为你的电脑里面没有Python,编写好的.py文件就没有解释器可以运行,所以安装Python环境/解释器就是最重要的一件事。PS:本文仅为笔记,为个人整理而成,如有不足之处请多多指正。目录第一步:下载1.官方网站2.镜像源网站第二步......
  • 基于Python+Flask实现宿舍管理系统
    作者主页:编程千纸鹤作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,有较为丰富的相关经验。期待......
  • 基于Python爬虫实现招聘数据分析可视化大屏
    作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,有较为丰富的相关经验。期待与各位高校教师、企业......
  • 快速排序算法详解及Python实现
    目录引言快速排序算法步骤快速排序的Python实现性能分析注意事项引言快速排序(QuickSort)是一种高效的排序算法,由C.A.R.Hoare在1960年提出。它的基本思想是:通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据要小,然后再按此......
  • python入门篇-day04-函数
    介绍概述函数也叫方法,可以用单词Function(函数,功能),Method(方法)来表示.函数=把具有独立功能的代码封装到一起,使其成为具有特殊功能的代码集.好处提到代码的复用性.模块化编程.格式def函数名(形式参数1,形参2...):  函数体,就是以前写的逻辑代......
  • python入门篇-day05-函数进阶
    函数返回多个值不管返回多少都会默认封装成一个元组的形式返回(可以自定义返回的数据类型,如:[]{})思考:1个函数可以同时返回多个结果(返回值)?答案:错误,因为1个函数只能返回1个结果,如果同时返回多个值则会封装成1个元素进行返回.演示#需求:定义函数my_cal......
  • Python教程(十五):IO 编程
    目录专栏列表引言基础概念什么是IO?同步IOvs异步IO同步IO(SynchronousIO)异步IO(AsynchronousIO)Python中的IO标准IO标准输入和输出文件IO文件操作的上下文管理器打开文件读取文件操作内存中的数据高级文件操作读写二进制文件使用文件指针网络IO使用`requests`库使用......
  • python自学
    基础语法字面量定义:在代码中,被写下来的值,称之为字面量类型:python中常用的有6种数据类型数字整数(int)浮点数(float)复数(complex),如4+3j布尔(bool):True本质为1,False本质为0字符串(String)字符串需要使用'xxx',"xxx"或者'''xxx'''格式,而三引号中的字符串可以跨行。......
  • python循环语句之while循环和for循环
    文章目录1.while循环1.1介绍1.1.1生活中的循环1.1.2程序中的循环1.2总结2.while循环应用:1~100求和2.1需求2.2分析3.while嵌套循环以及运用3.1while嵌套循环语句的语法格式3.2while嵌套循环使用3.2.1要求3.2.2参考代码4.for循环4.1for循环基本格式4.......
  • python判断语句之if语句、比较和逻辑运算符、if...else...语句、if...elif...else语句
    文章目录1.介绍1.1顺序语句1.2判断语句1.3循环语句2.if语句的基本格式2.1判断语句介绍2.2程序中的判断2.3if语句的基本格式3.比较和逻辑运算符3.1比较运算符3.2逻辑运算符4.if...else...语句4.1if...else...的语法格式4.2实例5.if...elif...else...语......