深入浅出:Python 中的异步编程与协程

server/2025/2/13 11:21:48/

引言

       大家好,今天我们来聊聊 异步编程协程,这是近年来编程语言领域中的热点话题之一,尤其在 Python 中,它作为一种全新的编程模型,已经成为处理 IO密集型 任务的强力工具。尽管很多人对异步编程望而却步,觉得它复杂难懂,但其实掌握了它,你就能感受到异步编程带来的速度提升,尤其是在高并发、网络爬虫、爬虫框架、聊天机器人等领域,异步编程简直是神器!

      所以,今天我们就从头开始,带你一步步搞懂异步编程和协程,带着你从基本概念到实际应用,通俗易懂又不失深度的讲解这项技术。

1. 什么是异步编程?

首先,来搞清楚异步编程同步编程到底有什么区别。

  • 同步编程:代码按照书写顺序逐行执行,每一行执行完,才会执行下一行。比如,你去餐厅点了菜,厨师开始做饭,直到你吃完饭才能结账离开,这个过程就叫做同步。

  • 异步编程:代码执行时,不会阻塞其他任务,可以让程序在等待某些任务的结果时,去做其他事情。继续以餐厅为例,当你点了菜后,厨师开始做饭,你可以先去刷会儿手机,聊天什么的,等做完了菜再叫你吃,这个过程就叫做异步。

      简单总结:同步是“做一件事等着做完”,而异步是“做事的时候,不等,去做其他事情”。如果我们把程序执行的时间浪费在等待 IO 操作(比如网络请求、数据库查询等)上,那就不如使用异步方式,让程序继续执行其他任务。

2. Python 中的异步编程

      在 Python 中,异步编程通常借助 asyncio 库来实现。asyncio 是 Python 的标准库之一,专门用于写异步 I/O 代码。Python 中的异步编程主要通过 协程 来实现。

2.1 什么是协程?

      在 Python 中,协程(Coroutine)是一种特殊的函数,它可以在执行过程中被暂停并在后续某个时间恢复执行。协程最常见的应用就是处理 I/O 操作(比如读取文件、发送网络请求等),因为这些操作可能需要等待一段时间,如果用同步代码,程序会一直等待,浪费了大量时间,而使用协程就能“挂起”执行并切换到其他任务。

你可以把协程想象成一个可以中途暂停并恢复的任务。这种灵活性非常适合处理大量并发 I/O 请求。

3. 如何写一个协程?

      Python 使用 asyncawait 关键字来定义和执行协程。让我们先看一个简单的例子:

import asyncioasync def hello_world():print("Hello")await asyncio.sleep(1)  # 模拟IO操作,暂停1秒print("World")# 运行协程
asyncio.run(hello_world())

      在上面的代码中:

  • async def 用来定义一个异步函数,也就是协程。
  • await 关键字用于在协程中调用另一个异步函数。在这个例子中,asyncio.sleep(1) 会暂停协程的执行 1 秒钟,模拟一个耗时的 I/O 操作。
  • asyncio.run() 用来启动协程。
4. 让多个协程并发执行

      协程的强大之处在于我们可以通过 asyncio 轻松地让多个任务并发执行。接下来,我们创建多个协程任务,让它们并行执行。

import asyncioasync def task(n):print(f"Task {n} started")await asyncio.sleep(2)print(f"Task {n} completed")async def main():# 创建多个任务并发执行tasks = [task(i) for i in range(5)]await asyncio.gather(*tasks)  # 等待所有任务完成asyncio.run(main())

      在上面的例子中,asyncio.gather(*tasks) 会将多个协程任务并行执行,而不是一个接一个地执行。这样,就能够在等待 I/O 操作的同时执行其他任务,充分利用时间。

5. 异步编程的优势

      异步编程最明显的优势就是它能够在高并发情况下提高程序的效率,尤其在处理大量 I/O 操作时(比如网络请求、文件读写等)。

  • 高效利用 CPU 资源:由于异步编程不会阻塞程序的执行,它允许 CPU 在等待 I/O 时去处理其他任务。
  • 减少延迟:在传统的同步方式中,IO 操作会造成大量的延迟,而异步编程可以在等待期间执行其他任务,从而减少整体的响应时间。
  • 处理大并发:使用异步编程,你可以在同一时间内启动成百上千的任务,而不会占用大量的系统资源。
6. 异步编程的陷阱

      尽管异步编程非常强大,但它也有一些潜在的陷阱,尤其是当你刚接触这个概念时:

  • 异步不适合所有任务:如果你的程序是 CPU 密集型的,异步编程反而可能导致性能下降。因为异步编程的优势主要体现在 I/O 密集型任务上。
  • 错误处理:在异步代码中,异常的处理和同步代码有些不同,特别是在并发执行的情况下,如何捕获并处理异常需要特别注意。
  • 调试困难:由于协程的执行是分散的,调试异步程序相对来说比同步程序更为复杂,尤其是在多个任务并行执行的情况下。
7. 异步与多线程的对比

      很多人会问,异步编程和多线程编程有何区别。简单来说:

  • 异步编程:是基于事件循环的方式,不需要多线程,适用于 I/O 密集型任务,通过非阻塞的方式提升并发度。
  • 多线程编程:是通过多个线程并行执行任务,适合计算密集型任务,但也带来了线程切换的开销和数据竞争等问题。

      异步编程的优势在于它能够在单个线程中高效地处理大量并发任务,而不会像多线程那样产生上下文切换的开销。

8. 实际应用案例:异步爬虫

      异步编程非常适合用来写爬虫程序。假设我们需要爬取多个网页,每个网页的请求都需要花费一定的时间,如果采用同步编程,程序就会一个接一个地等待每个网页的响应,效率低下。而使用异步编程,可以让爬虫程序在等待某个网页响应时,去请求其他网页。

下面是一个简单的异步爬虫示例:

import aiohttp
import asyncioasync def fetch_url(url):async with aiohttp.ClientSession() as session:async with session.get(url) as response:return await response.text()async def main():urls = ['http://example.com', 'http://example.org', 'http://example.net']tasks = [fetch_url(url) for url in urls]results = await asyncio.gather(*tasks)for result in results:print(result[:100])  # 打印前100个字符asyncio.run(main())

      在这个爬虫例子中,我们使用 aiohttp 库异步地请求多个网页,并且使用 asyncio.gather 来并行执行这些请求。这种方式比传统的同步爬虫效率更高,因为我们能够在等待网页响应时进行其他操作。

9. 总结

      通过本文的讲解,我们了解了 Python 中的异步编程以及协程的基本概念、应用场景以及注意事项。异步编程在处理大量 I/O 操作时能够显著提升程序的性能,特别是在高并发的情况下,它能够更高效地利用计算机资源。不过,异步编程并不是万灵药,适合 I/O 密集型任务,但对于 CPU 密集型任务,传统的多线程或多进程编程仍然更为高效。

      最后,异步编程的学习曲线可能有些陡峭,但一旦掌握了这一概念,它将为你开发高效、高性能的应用程序提供强大的支持!


http://www.ppmy.cn/server/167308.html

相关文章

Redis07 - Redis底层数据结构

Redis底层数据结构 文章目录 Redis底层数据结构一:对象机制详解二:SDS 简单动态字符串三:压缩列表zipList结构 四:跳表 一:对象机制详解 String类型 - 简单动态字符串SDSList类型 - 双向链表 & 压缩列表Set类型 - …

贪心算法_翻硬币

蓝桥账户中心 依次遍历 不符合条件就反转 题目要干嘛 你就干嘛 #include <bits/stdc.h>#define endl \n using namespace std;int main() {ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); string s; cin >> s;string t; cin >> t;int ret 0;for ( i…

【读书笔记·VLSI电路设计方法解密】问题44:什么是代码覆盖率

代码覆盖率&#xff08;Code Coverage&#xff09;与测试平台的概念密切相关。它是衡量测试平台质量的一种指标。通过使用特定的测试平台&#xff0c;对以HDL&#xff08;或其他高级语言&#xff09;构建的模块进行代码覆盖率分析&#xff0c;可以记录RTL源代码中哪些行被执行&…

碰一碰发视频源码技术开发,支持OEM

一、引言 在当今数字化信息快速传播的时代&#xff0c;碰一碰发视频这种便捷的数据交互方式正逐渐走进人们的生活。从技术实现角度来看&#xff0c;其后台开发逻辑是确保整个功能稳定运行的关键。本文将深入剖析碰一碰发视频后台开发的核心逻辑&#xff0c;为开发者提供技术参…

变化检测相关论文可读list

一些用得上的&#xff1a; 遥感变化检测常见数据集https://github.com/rsdler/Remote-Sensing-Change-Detection-Dataset/ 代码解读&#xff1a;代码解读 | 极简代码遥感语义分割&#xff0c;结合GDAL从零实现&#xff0c;以U-Net和建筑物提取为例 NeurIPS2024: https://mp.w…

【vs2022配置cursor】

Cursor搭配cmake实现C程序的编译、运行和调试的参考地址 cursor下载地址 第一步&#xff1a; 电脑上按爪cmake 第二步&#xff1a;cursor 配置 安装中文 第三步环境变量&#xff1a; D:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.35.322…

数据结构:队列

1.概念&#xff1a; 和栈相反&#xff0c;队列是一种先进先出的线性表它只允许在标的一段进行插入&#xff0c;而在另一端进行删除元素。这和我们日常生活中的排队是一致的&#xff0c;即最早入队的元素最早离开。队列中允许插入的一端叫做队尾&#xff0c;允许删除的一端的叫…

【云安全】云原生-K8S- API Server 未授权访问

API Server 是 Kubernetes 集群的核心管理接口&#xff0c;所有资源请求和操作都通过 kube-apiserver 提供的 API 进行处理。默认情况下&#xff0c;API Server 会监听两个端口&#xff1a;8080 和 6443。如果配置不当&#xff0c;可能会导致未授权访问的安全风险。 8080 端口…