Python async模块使用方法杂谈

yizhihongxing

Python async模块使用方法杂谈

Python async(协程)是近年来非常流行的一种异步编程模式。async通过事件循环机制和协程技术实现其非阻塞的异步效果,让我们能够更方便、高效地编写异步代码。在本文中,我们将详细讲解Python async模块的使用方法,并带有两个示例说明。

1.异步编程概述

在传统的编程模式中,当程序执行到一个耗时的I/O操作后,程序会一直阻塞在这个操作上,直到I/O操作完成并返回结果。而在异步编程模式中,当程序执行到IO操作时,它不会被一直阻塞,而是可以去处理其他事情,避免了阻塞时间导致的不必要等待。

异步编程是在事件循环(Eventloop)的基础上完成的,协程(Coroutine)则是实现异步编程的核心技术。事件循环相当于一个消息处理器,从消息队列中取出消息,并将确定是能够立即处理的消息传递给对应的协程进行处理。

2.asyncio模块

Python3.4版本后,官方提供的异步编程模块就是asyncio(前身是tulip)。asyncio提供了事件循环机制,并且asyncio也提供了协程的支持,支持异步I/O和并发任务执行,因此是开发异步I/O服务的一个很好的选择。

asyncio模块常用函数和类

  • asyncio.create_task(协程对象):将协程包装为任务。
  • asyncio.wait(aws, timeout=None, return_when=ALL_COMPLETED):并行运行一个任务列表,aws是任务列表,timeout是等待的秒数,return_when的值可以是WAIT_FIRST_COMPLETED、ALL_COMPLETED或FIRST_EXCEPTION。
  • asyncio.gather(aws, *, loop=None, return_exceptions=False):并行运行一个协程列表,会在所有协程执行完成后返回结果。
  • asyncio.sleep():模拟时间的等待,是一个异步调用。
  • asyncio.Queue():一个异步队列,可以并发的进行put和get操作。

更多的函数和类请查看asyncio的官方文档。

3.说明示例:多任务异步I/O并行执行

接下来我们来看一个简单的示例,实现多任务异步I/O并行执行:

import asyncio
import time

async def do_work(num):
    print("start to work {}".format(num))
    await asyncio.sleep(1) # 模拟异步I/O
    print("work {} has been completed.".format(num))
    return num

async def main():
    tasks = [asyncio.create_task(do_work(i)) for i in range(1, 11)]
    await asyncio.wait(tasks)

if __name__ == '__main__':
    start_time = time.time()
    asyncio.run(main())
    print("time used: ", time.time() - start_time)

在本示例中,我们实现了10个协程任务的异步并行执行,每个任务都等待1秒钟后返回结果。通过asyncio.create_task()将每个异步任务都打包为任务,并将返回的任务列表传递给asyncio.wait()函数,该函数将异步执行所有任务并等待它们全部完成之后才结束。通过time.time()获取程序从开始执行到结束所消耗的时间。

输出结果如下:

start to work 1
start to work 2
start to work 3
start to work 4
start to work 5
start to work 6
start to work 7
start to work 8
start to work 9
start to work 10
work 1 has been completed.
work 2 has been completed.
work 3 has been completed.
work 4 has been completed.
work 5 has been completed.
work 6 has been completed.
work 7 has been completed.
work 8 has been completed.
work 9 has been completed.
work 10 has been completed.
time used:  1.00295090675354

如上输出所示,10个任务都在1秒钟之内完成了,说明它们是异步并行执行的。

4.说明示例:生产者-消费者模式

接下来,我们来看一个更复杂的示例,实现生产者-消费者模式。其中,生产者通过一个异步队列生产数据,而消费者则从队列中读取数据并进行处理。

import asyncio
import random

async def producer(queue, id):
    while True:
        item = random.randint(0, 99)
        print("Producer {} produced {}".format(id, item))
        await queue.put(item)
        await asyncio.sleep(0.5)

async def consumer(queue, id):
    while True:
        item = await queue.get()
        print("Consumer {} consumed {}".format(id, item))
        await asyncio.sleep(1)

async def main():
    queue = asyncio.Queue()
    producers = [asyncio.create_task(producer(queue, i)) for i in range(3)]
    consumers = [asyncio.create_task(consumer(queue, i)) for i in range(2)]

    await asyncio.sleep(10) # 等待10秒钟后结束任务
    for prod in producers:
        prod.cancel() # 取消生产者任务
    await asyncio.gather(*producers, return_exceptions=True) # 等待正在运行的任务完成
    await queue.join() # 等待队列清空
    for cons in consumers:
        cons.cancel() # 取消消费者任务

if __name__ == '__main__':
    asyncio.run(main())

在本示例中,我们定义了两个协程任务:生产者和消费者,在主函数中创建了一个异步队列,分别创建了3个生产者和2个消费者,每个生产者将随机生成的数据放入队列中,每个消费者从队列中取出数据并进行处理。在主函数中等待10秒钟后结束生产者任务,并等待队列清空后结束消费者任务。

输出结果如下:

Producer 0 produced 10
Consumer 0 consumed 10
Producer 1 produced 12
Consumer 1 consumed 12
Producer 2 produced 20
Consumer 0 consumed 20
Producer 0 produced 63
Consumer 1 consumed 63
Producer 1 produced 74
Producer 0 produced 81
Consumer 0 consumed 74
Consumer 0 consumed 81
Producer 2 produced 88
Consumer 1 consumed 88
.
.
.
Producer 1 produced 12
Consumer 0 consumed 12
Producer 0 produced 65
Consumer 1 consumed 65
Producer 1 produced 45
Consumer 0 consumed 45

如上输出所示,生产者和消费者协同工作,实现了异步的生产和消费,从而构建了生产者-消费者模式。

总结:异步编程是提高代码效率的一种重要的手段,Python的async模块提供了一套完整的异步编程解决方案。了解它的基本使用方法,可以帮助我们更高效地编写异步程序。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python async模块使用方法杂谈 - Python技术站

(0)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • 详解python调用cmd命令三种方法

    下面是关于“详解Python调用cmd命令三种方法”的完整攻略: 概述 在Python中,我们可以使用subprocess模块来调用命令行(cmd)命令。在这里,我们将介绍三种使用subprocess模块调用命令行命令的方法,以及如何在出现错误时处理它们。 三种方法 方法一:使用subprocess.call() subprocess.call()函数可以执…

    python 2023年6月2日
    00
  • python基于urllib实现按照百度音乐分类下载mp3的方法

    下面是Python基于urllib实现按照百度音乐分类下载MP3的方法的完整攻略。 1. 确认需求 在开始编写程序之前,首先需要确认我们所要实现的需求,即:按照百度音乐的分类,从网站上下载对应的MP3文件。 2. 分析问题 在确认需求之后,需要具体分析如何实现这个需求。 2.1 获取音乐列表 首先,我们需要获取百度音乐的分类列表。打开百度音乐分类页面,我们可…

    python 2023年6月3日
    00
  • Python报错:ModuleNotFoundError的解决办法

    当我们在Python编程过程中,有时会遇到ModuleNotFoundError的报错。这通常是由于Python环境配置不正确、Python库缺失或路径不正确等因引起的。以下是一些常见的ModuleNotFoundError报错的解决方案: 1. 安装缺失的Python库 如果在Python编程过程中到了类似以下的报错: ModuleNotFoundErro…

    python 2023年5月13日
    00
  • Python中变量的输入输出实例代码详解

    Python中变量输入输出实例代码详解 本文主要介绍Python中变量的输入输出实例代码,包括Python中的标准输入输出和文件的输入输出。 标准输入输出 输入变量 要在Python中输入变量,可以使用内置函数input()。函数参数作为提示信息在屏幕上输出,用户输入变量并按Enter结束输入。 示例代码: # 输入变量并输出 name = input(&q…

    python 2023年5月31日
    00
  • pip报错“ValueError: invalid literal for int() with base 10: ‘2.1’”怎么处理?

    当使用pip安装Python包时,可能会遇到“ValueError: invalid literal for int() with base 10: ‘2.1’”错误。这个错误通常是由以下原因之一引起的: 包版本号格式不正确:如果包版本号格式不正确,则可能会出现此错误。在这种情况下,需要更改包版本号格式。 pip版本过低:如果pip版本过低,则可能会出现此错…

    python 2023年5月4日
    00
  • Python list sort方法的具体使用

    以下是详细讲解“Python list sort方法的具体使用”的完整攻略。 在Python中,列表是一种常用的数据类型,可以用存储一组有序的数据。sort()是Python中用于对列表进行排序的方法。本文介绍sort()方法的具体使用方法,并提两个示例说明。 sort()方法的具体使用 sort()方法用于对列表进行排序可以按照升序或降序排列。sort()…

    python 2023年5月13日
    00
  • Python3 pickle模块的使用方法详细介绍

    Python3 pickle模块的使用方法详细介绍 pickle模块是Python提供的一种对象序列化和反序列化的工具,能够将Python对象转换为一个可以存储到磁盘上或者进行网络传输的字符串,同时也能够将这个字符串反序列化为原来的Python对象。使用pickle模块可以方便地实现数据的持久化和传输,是Python编程中非常重要的一部分。 序列化和反序列化…

    python 2023年6月2日
    00
  • 简介二分查找算法与相关的Python实现示例

    下面是详细讲解“简介二分查找算法与相关的Python实现示例”的完整攻略。 二分查找算法 二分查找算法(Binary Search Algorithm)是一种常用的查找算法,用于在有序数组中查找指定元素。该算法的核心思想是将数组分成两份,判断目标元素在哪一部分中然后继续在该部分中查找,直到找到目标元素或者确定标元素不存在。 二分查找算法的时间复杂度为O(lo…

    python 2023年5月14日
    00
合作推广
合作推广
分享本页
返回顶部