Python asyncio:入门指南

422 阅读3分钟

asyncio 是Python 3.5及更高版本中的一个库,它提供了一种写并发代码的方法,使用 async/await 语法。这使得编写并发代码变得更加简单和直观。本文将深入探讨如何使用 asyncio,从基础到高级。

1. 为什么选择 asyncio

在开始之前,我们先了解一下为什么要使用 asyncio

  • 性能优化:异步编程允许我们同时执行多个操作,从而提高程序的总体效率。
  • 简洁的语法:与传统的线程和进程相比,async/await 语法更加简洁和易于理解。

2. 入门

2.1 什么是 asyncawait

  • async 定义一个异步函数,该函数返回一个可等待对象。
  • await 用于等待一个异步操作完成。
import asyncio

async def hello_world():
    print("Hello")
    await asyncio.sleep(1)
    print("World")

asyncio.run(hello_world())

2.2 事件循环

事件循环是 asyncio 的核心。它可以注册、取消和执行任务。

loop = asyncio.get_event_loop()
loop.run_until_complete(hello_world())

3. 进阶

3.1 任务

任务是用于并发执行的 asyncio 的基本单位。

task = asyncio.create_task(hello_world())

3.2 期望

期望是一种特殊的对象,表示一个将在未来完成的计算。

future = loop.create_future()

3.3 异步迭代器和异步生成器

这两者都是 asyncio 的高级功能,允许异步迭代和生成。

async def async_gen():
    for i in range(5):
        await asyncio.sleep(1)
        yield i

async for i in async_gen():
    print(i)

4. 真实世界的例子

4.1 异步网络请求

对于异步的网络请求,我们通常使用 aiohttp 库。首先,您需要安装这个库:

pip install aiohttp

以下是一个简单的异步获取网页内容的例子:

import aiohttp
import asyncio

async def fetch_url(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            return await response.text()

async def main():
    content = await fetch_url("https://www.example.com")
    print(content)

asyncio.run(main())

4.2 异步文件I/O

尽管Python的内置文件操作不是异步的,但我们可以使用 aiofiles 库来异步地读写文件。首先,您需要安装这个库:

pip install aiofiles

以下是异步读取文件的一个例子:

import aiofiles
import asyncio

async def read_file(filename):
    async with aiofiles.open(filename, mode='r') as file:
        return await file.read()

async def main():
    content = await read_file("example.txt")
    print(content)

asyncio.run(main())

4.3 协程间通信

asyncio 提供了 Queue 作为协程间的通信机制。以下是一个简单的生产者消费者模型的例子:

import asyncio

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

async def consumer(queue):
    for _ in range(5):
        item = await queue.get()
        print(f"Consumed {item}")

async def main():
    queue = asyncio.Queue()
    prod_task = asyncio.create_task(producer(queue))
    cons_task = asyncio.create_task(consumer(queue))

    await asyncio.gather(prod_task, cons_task)

asyncio.run(main())

5. asyncio 常用方法和功能

  1. asyncio.run(coro)

    • 说明:作为 asyncio 程序的主入口点,用于执行一个协程。
    • 示例asyncio.run(main())
  2. asyncio.create_task(coro)

    • 说明:并发地运行协程作为 asyncio 任务。
    • 示例task = asyncio.create_task(my_coroutine())
  3. asyncio.sleep(delay)

    • 说明:返回一个表示指定延迟的异步可等待对象。
    • 示例await asyncio.sleep(1)
  4. asyncio.gather(*coros)

    • 说明:并发地运行所有给定的协程或者异步任务。
    • 示例await asyncio.gather(task1(), task2(), task3())
  5. asyncio.Queue()

    • 说明:提供了一个异步的先入先出队列。常用于协程之间的通信和同步。
    • 示例queue = asyncio.Queue()
  6. asyncio.wait_for(coro, timeout)

    • 说明:等待协程完成,但有最大超时时间。
    • 示例await asyncio.wait_for(my_coroutine(), timeout=2)
  7. asyncio.wait(tasks, return_when=ALL_COMPLETED)

    • 说明:等待给定的异步任务或协程完成。return_when 参数可以指定何时返回。
    • 示例await asyncio.wait([task1, task2], return_when=asyncio.FIRST_COMPLETED)
  8. asyncio.Lock()

    • 说明:异步实现的互斥锁。
    • 示例
      lock = asyncio.Lock()
      async with lock:
          # critical section of code
      
  9. asyncio.Event()

    • 说明:提供了一个简单的异步事件系统。
    • 示例
      event = asyncio.Event()
      await event.wait()
      event.set()
      
  10. asyncio.Semaphore(value=1)

  • 说明:提供了一个异步的信号量。
  • 示例
    sem = asyncio.Semaphore(10)
    async with sem:
        # section of code that uses the resource
    
  1. asyncio.Future()
  • 说明:代表一个异步操作的最终结果。通常不需要手动创建,任务(Task)是它的子类,更常用于实际应用。
  • 示例future = asyncio.Future()
  1. loop.call_later(delay, callback, *args)
  • 说明:在给定的 delay 秒数后,执行指定的回调。
  • 示例loop.call_later(5, print, "Hello after 5 seconds")

6. 总结

asyncio 提供了一种高效、简洁的方式来编写并发代码。通过掌握其基础和高级功能,您可以充分利用Python的异步能力,为您的应用带来更好的性能。