首页 后端开发 Python教程 高性能 Python:Asyncio

高性能 Python:Asyncio

Jan 01, 2025 am 06:30 AM

High-Performance Python: Asyncio

并发编程是一种处理多个任务同时执行的编程方法。在Python中,asyncio是实现异步编程的强大工具。基于协程的概念,asyncio 可以高效地处理 I/O 密集型任务。本文将介绍asyncio的基本原理和使用方法

High-Performance Python: Asyncio

为什么我们需要 asyncio

我们知道,在处理I/O操作时,使用多线程相比普通的单线程可以大大提高效率。那么,为什么我们还需要 asyncio?

多线程有很多优点,应用广泛,但也有一定的局限性:

  • 例如多线程的运行过程很容易被中断,因此可能会出现race condition的情况。
  • 而且,线程切换本身是有一定成本的,线程数不可能无限增加。因此,如果你的I/O操作非常繁重,多线程很可能无法满足高效率和高质量的要求。

正是为了解决这些问题,asyncio 应运而生。

同步 VS 异步

我们先区分一下Sync(同步)和Async(异步)的概念。

  • 同步是指操作依次执行。前一个操作完成后才能执行下一个操作。
  • 异步意味着不同的操作可以交替执行。如果其中一项操作被阻塞,程序不会等待,而是会寻找可执行的操作来继续。

异步如何工作

  1. 协程:asyncio 使用协程来实现异步操作。协程是使用 async 关键字定义的特殊函数。在协程中,await 关键字可用于暂停当前协程的执行并等待异步操作完成。
  2. 事件循环:事件循环是asyncio的核心机制之一。它负责调度和执行协程并处理协程之间的切换。事件循环将不断轮询可执行任务。一旦任务准备就绪(例如 I/O 操作完成或计时器到期),事件循环会将其放入执行队列并继续执行下一个任务。
  3. 异步任务:在asyncio中,我们通过创建异步任务来执行协程。异步任务由 asyncio.create_task() 函数创建,该函数将协程封装成一个可等待的对象,并将其提交给事件循环进行处理。
  4. 异步I/O操作:asyncio提供了一组异步I/O操作(如网络请求、文件读写等),可以通过等待关键字。通过使用异步I/O操作,可以避免等待I/O完成期间的阻塞,提高程序性能和并发性。
  5. 回调:asyncio还支持使用回调函数来处理异步操作的结果。 asyncio.ensure_future() 函数可用于将回调函数封装成可等待对象,并将其提交给事件循环进行处理。
  6. 并发执行:asyncio可以并发执行多个协程任务。事件循环会根据任务的就绪情况自动调度协程的执行,从而实现高效的并发编程。

综上所述,asyncio的工作原理是基于协程和事件循环的机制。 asyncio 通过使用协程进行异步操作,并让事件循环负责协程的调度和执行,实现了高效的异步编程模型。

协程和异步编程

协程是 asyncio 中的一个重要概念。它们是轻量级执行单元,可以在任务之间快速切换,而无需线程切换的开销。可以使用 async 关键字定义协程,await 关键字用于暂停协程的执行,并在某个操作完成后恢复。

这是一个简单的示例代码,演示如何使用协程进行异步编程:

import asyncio

async def hello():
    print("Hello")
    await asyncio.sleep(1)  # Simulate a time-consuming operation
    print("World")

# Create an event loop
loop = asyncio.get_event_loop()

# Add the coroutine to the event loop and execute
loop.run_until_complete(hello())
登录后复制
登录后复制

在此示例中,函数 hello() 是使用 async 关键字定义的协程。在协程内部,我们可以使用await来暂停其执行。这里使用asyncio.sleep(1)来模拟一个耗时的操作。 run_until_complete() 方法将协程添加到事件循环中并运行它。

异步 I/O 操作

asyncio主要用于处理I/O密集型任务,如网络请求、文件读写等。它提供了一系列异步I/O操作的API,可以与await关键字结合使用,轻松实现异步编程。

这是一个简单的示例代码,展示了如何使用 asyncio 进行异步网络请求:

import asyncio
import aiohttp

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    async with aiohttp.ClientSession() as session:
        html = await fetch(session, 'https://www.example.com')
        print(html)

# Create an event loop
loop = asyncio.get_event_loop()

# Add the coroutine to the event loop and execute
loop.run_until_complete(main())
登录后复制
登录后复制

在此示例中,我们使用 aiohttp 库来处理网络请求。函数 fetch() 是一个协程。它通过session.get()方法发起异步GET请求,并使用await关键字等待响应返回。函数 main() 是另一个协程。它在内部创建一个 ClientSession 对象以供复用,然后调用 fetch() 方法获取网页内容并打印。

注意:这里我们使用aiohttp而不是requests库,因为requests库不兼容asyncio,而aiohttp库则兼容。想要用好asyncio,尤其是发挥其强大的功能,很多时候需要相应的Python库。

多个任务并发执行

asyncio还提供了一些并发执行多个任务的机制,例如asyncio.gather()和asyncio.wait()。下面是一个示例代码,展示了如何使用这些机制来并发执行多个协程任务:

import asyncio

async def task1():
    print("Task 1 started")
    await asyncio.sleep(1)
    print("Task 1 finished")

async def task2():
    print("Task 2 started")
    await asyncio.sleep(2)
    print("Task 2 finished")

async def main():
    await asyncio.gather(task1(), task2())

# Create an event loop
loop = asyncio.get_event_loop()

# Add the coroutine to the event loop and execute
loop.run_until_complete(main())
登录后复制
登录后复制

在这个例子中,我们定义了两个协程任务task1()和task2(),它们都执行一些耗时的操作。协程 main() 通过 asyncio.gather() 同时启动这两个任务并等待它们完成。并发执行可以提高程序执行效率。

如何选择?

实际项目中,我们应该选择多线程还是asyncio?有大佬总结的很形象:

import asyncio

async def hello():
    print("Hello")
    await asyncio.sleep(1)  # Simulate a time-consuming operation
    print("World")

# Create an event loop
loop = asyncio.get_event_loop()

# Add the coroutine to the event loop and execute
loop.run_until_complete(hello())
登录后复制
登录后复制
  • 如果是 I/O 绑定,并且 I/O 操作很慢,需要很多任务/线程的配合,那么使用 asyncio 更合适。
  • 如果是 I/O 绑定,但 I/O 操作很快并且只需要有限数量的任务/线程,那么多线程就可以了。
  • 如果是CPU密集型,那么就需要多处理来提高程序运行效率。

实践

输入一个列表。对于列表中的每个元素,我们要计算从 0 到该元素的所有整数的平方和。

同步实施

import asyncio
import aiohttp

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    async with aiohttp.ClientSession() as session:
        html = await fetch(session, 'https://www.example.com')
        print(html)

# Create an event loop
loop = asyncio.get_event_loop()

# Add the coroutine to the event loop and execute
loop.run_until_complete(main())
登录后复制
登录后复制

执行时间为计算耗时16.00943413000002秒

使用并发.futures 进行异步实现

import asyncio

async def task1():
    print("Task 1 started")
    await asyncio.sleep(1)
    print("Task 1 finished")

async def task2():
    print("Task 2 started")
    await asyncio.sleep(2)
    print("Task 2 finished")

async def main():
    await asyncio.gather(task1(), task2())

# Create an event loop
loop = asyncio.get_event_loop()

# Add the coroutine to the event loop and execute
loop.run_until_complete(main())
登录后复制
登录后复制

执行时间为计算耗时 7.314132894999999 秒

在这段改进后的代码中,我们使用concurrent.futures.ProcessPoolExecutor创建进程池,然后使用executor.map()方法提交任务并获取结果。注意,使用 executor.map() 后,如果需要获取结果,可以将结果迭代到列表中,或者使用其他方法处理结果。

多处理实现

if io_bound:
    if io_slow:
        print('Use Asyncio')
    else:
        print('Use multi-threading')
elif cpu_bound:
    print('Use multi-processing')
登录后复制

执行时间为计算耗时5.024221667秒

concurrent.futures.ProcessPoolExecutor和multiprocessing都是Python中用于实现多进程并发的库。有一些差异:

  1. 基于接口的封装:concurrent.futures.ProcessPoolExecutor是concurrent.futures模块提供的高级接口。它封装了底层的多进程函数,使编写多进程代码变得更加容易。而multiprocessing是Python的标准库之一,提供完整的多进程支持,并允许直接对进程进行操作。
  2. API 用法:concurrent.futures.ProcessPoolExecutor 的用法与线程池类似。它将可调用的对象(例如函数)提交到进程池执行,并返回一个Future对象,可以用来获取执行结果。多处理提供了更多低级进程管理和通信接口。可以显式地创建、启动和控制进程,并且可以使用队列或管道来完成多个进程之间的通信。
  3. 可扩展性和灵活性:由于多处理提供了更多底层接口,因此与concurrent.futures.ProcessPoolExecutor相比更加灵活。通过直接操作进程,可以对每个进程实现更细粒度的控制,如设置进程优先级、进程间共享数据等。 concurrent.futures.ProcessPoolExecutor 更适合简单的任务并行化,隐藏了很多底层细节,更容易编写多进程代码。
  4. 跨平台支持:concurrent.futures.ProcessPoolExecutor 和 multiprocessing 都提供跨平台多进程支持,可以在各种操作系统上使用。

综上所述,concurrent.futures.ProcessPoolExecutor是一个高层接口,封装了底层多进程功能,适合简单的多进程任务并行化。 multiprocessing是一个更底层的库,提供了更多的控制和灵活性,适合需要对流程进行细粒度控制的场景。您需要根据具体需求选择合适的库。如果只是简单的任务并行化,可以使用concurrent.futures.ProcessPoolExecutor来简化代码;如果需要更多底层控制和通信,您可以使用多处理库。

概括

与多线程不同,asyncio 是单线程的,但其内部事件循环的机制允许它同时运行多个不同的任务,并且比多线程具有更强的自主控制能力。

asyncio中的任务在运行过程中不会被中断,因此不会出现race condition的情况。

尤其是在I/O操作繁重的场景下,asyncio比多线程有更高的运行效率。因为asyncio中任务切换的成本远小于线程切换的成本,而且asyncio可以启动的任务数量远大于多线程中的线程数量。

但是需要注意的是,很多情况下,使用asyncio需要特定的第三方库的支持,比如上例中的aiohttp。而如果I/O操作又快又不重的话,使用多线程也能有效解决问题。

  • asyncio 是一个用于实现异步编程的 Python 库。
  • 协程是asyncio的核心概念,通过async和await关键字实现异步操作。
  • asyncio 为异步 I/O 操作提供了强大的 API,可以轻松处理 I/O 密集型任务。
  • 通过asyncio.gather()等机制,可以并发执行多个协程任务。

Leapcell:FastAPI、Flask 和其他 Python 应用程序的理想平台

最后介绍一下部署Flask/FastAPI的理想平台:Leapcell。

Leapcell是专为现代分布式应用程序设计的云计算平台。其按需付费的定价模式确保没有闲置成本,这意味着用户只需为他们实际使用的资源付费。

High-Performance Python: Asyncio

  1. 多语言支持
    • 支持 JavaScript、Python、Go 或 Rust 开发。
  2. 免费部署无限项目
    • 仅根据使用情况收费。没有要求时不收费。
  3. 无与伦比的成本效益
    • 即用即付,无闲置费用。
    • 例如,25 美元可以支持 694 万个请求,平均响应时间为 60 毫秒。
  4. 简化的开发者体验
    • 直观的用户界面,易于设置。
    • 完全自动化的 CI/CD 管道和 GitOps 集成。
    • 实时指标和日志,提供可操作的见解。
  5. 轻松的可扩展性和高性能
    • 自动伸缩,轻松应对高并发。
    • 零运营开销,让开发者专注于开发。

在文档中了解更多信息!
Leapcell Twitter:https://x.com/LeapcellHQ

以上是高性能 Python:Asyncio的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1657
14
CakePHP 教程
1415
52
Laravel 教程
1309
25
PHP教程
1257
29
C# 教程
1229
24
Python vs.C:申请和用例 Python vs.C:申请和用例 Apr 12, 2025 am 12:01 AM

Python适合数据科学、Web开发和自动化任务,而C 适用于系统编程、游戏开发和嵌入式系统。 Python以简洁和强大的生态系统着称,C 则以高性能和底层控制能力闻名。

Python:游戏,Guis等 Python:游戏,Guis等 Apr 13, 2025 am 12:14 AM

Python在游戏和GUI开发中表现出色。1)游戏开发使用Pygame,提供绘图、音频等功能,适合创建2D游戏。2)GUI开发可选择Tkinter或PyQt,Tkinter简单易用,PyQt功能丰富,适合专业开发。

您可以在2小时内学到多少python? 您可以在2小时内学到多少python? Apr 09, 2025 pm 04:33 PM

两小时内可以学到Python的基础知识。1.学习变量和数据类型,2.掌握控制结构如if语句和循环,3.了解函数的定义和使用。这些将帮助你开始编写简单的Python程序。

2小时的Python计划:一种现实的方法 2小时的Python计划:一种现实的方法 Apr 11, 2025 am 12:04 AM

2小时内可以学会Python的基本编程概念和技能。1.学习变量和数据类型,2.掌握控制流(条件语句和循环),3.理解函数的定义和使用,4.通过简单示例和代码片段快速上手Python编程。

Python与C:学习曲线和易用性 Python与C:学习曲线和易用性 Apr 19, 2025 am 12:20 AM

Python更易学且易用,C 则更强大但复杂。1.Python语法简洁,适合初学者,动态类型和自动内存管理使其易用,但可能导致运行时错误。2.C 提供低级控制和高级特性,适合高性能应用,但学习门槛高,需手动管理内存和类型安全。

Python和时间:充分利用您的学习时间 Python和时间:充分利用您的学习时间 Apr 14, 2025 am 12:02 AM

要在有限的时间内最大化学习Python的效率,可以使用Python的datetime、time和schedule模块。1.datetime模块用于记录和规划学习时间。2.time模块帮助设置学习和休息时间。3.schedule模块自动化安排每周学习任务。

Python:探索其主要应用程序 Python:探索其主要应用程序 Apr 10, 2025 am 09:41 AM

Python在web开发、数据科学、机器学习、自动化和脚本编写等领域有广泛应用。1)在web开发中,Django和Flask框架简化了开发过程。2)数据科学和机器学习领域,NumPy、Pandas、Scikit-learn和TensorFlow库提供了强大支持。3)自动化和脚本编写方面,Python适用于自动化测试和系统管理等任务。

Python:自动化,脚本和任务管理 Python:自动化,脚本和任务管理 Apr 16, 2025 am 12:14 AM

Python在自动化、脚本编写和任务管理中表现出色。1)自动化:通过标准库如os、shutil实现文件备份。2)脚本编写:使用psutil库监控系统资源。3)任务管理:利用schedule库调度任务。Python的易用性和丰富库支持使其在这些领域中成为首选工具。

See all articles