博客
关于我
Python asyncio库的学习和使用
阅读量:804 次
发布时间:2023-03-05

本文共 2259 字,大约阅读时间需要 7 分钟。

Python 异步编程:理解 async 和 await 的执行顺序

在编写爬虫脚本时,经常会遇到性能瓶颈问题。传统的 requests + 多线程/多进程 方法虽然能够提高并发度,但由于其阻塞性,往往导致资源消耗过大,尤其是在等待网页响应和处理数据时。为了应对这一问题,Python 3.4 及及以上版本引入了异步 IO 编程模型,通过 asyncawait 关键字实现非阻塞式操作。

understanding async 和 await 的执行顺序

在理解 asyncawait 之前,首先需要明确阻塞调用和非阻塞调用之间的区别:

  • 阻塞调用:调用结果返回之前,当前线程会被挂起,无法执行其他任务,直到结果返回。
  • 非阻塞调用:调用结果返回后,立即返回给调用者,执行程序的其他部分。
  • 在 Python 中,asyncawait 是实现异步 IO 的关键工具。从 Python 3.5 开始,asyncawait 取代了之前的 @asyncio.coroutineyield from,使得代码更加直观。

    一个简单的示例说明

    以下是官方示例代码,用于说明 asyncawait 的执行顺序:

    import asyncioasync def compute(x, y):    print("Compute %s + %s ..." % (x, y))    await asyncio.sleep(1.0)  # 非阻塞式睡眠    return x + yasync def print_sum(x, y):    result = await compute(x, y)    print("%s + %s = %s" % (x, y, result))loop = asyncio.get_event_loop()loop.run_until_complete(print_sum(1, 2))loop.close()

    传统方式执行顺序

    如果没有使用 asyncawait,程序的执行流程是:

  • 调用 print_sum(1, 2)
  • 将参数传递给 compute(1, 2)
  • 执行 print("Compute 1 + 2 ...")
  • 睡眠 1 秒。
  • 返回结果 3
  • 打印 "1 + 2 = 3"
  • 程序结束。
  • 异步方式执行顺序

    使用 asyncawait 后,执行流程如下:

  • 调用 print_sum(1, 2)
  • 非阻塞式执行 compute(1, 2),即同时启动 compute
  • 执行 print("Compute 1 + 2 ...") 并等待 1 秒。
  • 返回结果 3
  • 执行 print("1 + 2 = 3")
  • 事件循环与任务

    在异步编程中,事件循环(event loop)扮演着核心角色。它负责管理和调度任务(tasks),确保每个任务按正确顺序执行。

    • event loop:负责检测和处理 I/O 事件。
    • tasks:异步操作的执行单元,由 asyncio.Futureasyncio.Task 实现。

    在上述代码中,get_event_loop() 获取事件循环,run_until_complete() 方法运行指定的协程对象,并返回控制权。

    优化后的代码示例

    为了更直观地理解异步执行顺序,可以稍作修改:

    import asyncioasync def compute(x, y):    print("Compute %s + %s ..." % (x, y))    await asyncio.sleep(10.0)  # 非阻塞式睡眠    return x + yasync def print_sum(x, y):    result = await compute(x, y)    print("%s + %s = %s" % (x, y, result))loop = asyncio.get_event_loop()tasks = [print_sum(1, 2), print_sum(3, 4)]loop.run_until_complete(asyncio.wait(tasks))loop.close()

    执行结果解析

    在此优化后的代码中,sleep(10.0) 被修改为更长的睡眠时间,以更直观地观察任务执行顺序:

  • print_sum(3, 4):首先提交任务,立即返回,开始计算 3 + 4
  • sleep(10.0):非阻塞式执行,等待 10 秒。
  • print_sum(1, 2):立即提交任务,开始计算 1 + 2
  • sleep(10.0):非阻塞式执行,等待 10 秒。
  • 最终结果显示:

    Compute 3 + 4 ...Compute 1 + 2 ...暂停 10 秒左右3 + 4 = 71 + 2 = 3

    从执行结果可以看出,事件循环会先完成所有已提交的任务,并等待所有任务完成后才继续后续操作。

    总结

    通过以上示例,可以清晰地看到 asyncawait 在异步编程中的重要作用。它们允许在不阻塞主线程的情况下,非顺序地执行任务,显著提升了爬虫等 I/O 驱动型任务的性能表现。理解事件循环和任务的执行机制,是掌握异步编程的关键。

    如果需要更深入的理解,可以参考相关的技术文档或博客。例如,了解 asyncio.Future 的实现机制,以及如何在实际应用中高效地利用异步编程。

    转载地址:http://jvafk.baihongyu.com/

    你可能感兴趣的文章
    python 利用pyspark读取HDFS中CSV文件的指定列 列名重命名 并保存回HDFS
    查看>>
    python 利用pyttsx3文字转语音
    查看>>
    python 利用已有Ner模型进行数据清洗合并
    查看>>
    python 到大数据开发工程师_如何成为一个大数据开发工程师?
    查看>>
    python 加密解密(base64, AES)
    查看>>
    Python 包管理器和 Node.js
    查看>>
    Python 单词字母顺序不变且所有倒排
    查看>>
    python 启动提示IDLE's subprocess didn't make conne...
    查看>>
    python 命令接口_实现“[命令][操作][参数]”样式的命令行接口?
    查看>>
    Python 和 OpenCV.如何检测图像中的所有(填充)圆形/圆形对象?
    查看>>
    Python 和 RabbitMQ - 聆听来自多个渠道的消费事件的最佳方式?
    查看>>
    python编辑器打不开_关于命令ride.py打不开RF,而是打开pycharm编辑器问题解决思路...
    查看>>
    python编译exe同时支持32位_第三周:同时管理64位和32位版本的Python,并用Pyinstaller打包成exe...
    查看>>
    Python 和Java 哪个更适合做自动化测试?
    查看>>
    Python编程:掌握高级语言程序设计。从零基础到精通,收藏这篇就够了!
    查看>>
    python 图片转ico
    查看>>
    python 图片转文字、语音转文字、文字转语音保存音频并朗读
    查看>>
    python 在包含类似字符\x16、\x12、\x某某的数组中将以\x开头的字符找出来的方法
    查看>>
    Python 在并行进程之间共享字典
    查看>>
    Python 垃圾收集器文档
    查看>>