asyncio 模块。asyncio 模块提供了出色的功能,允许我们编写更高效的 Python 异步应用程序。我们将探讨如何在 Python 中管理异步事件循环。在深入研究这个主题之前,让我们先了解什么是异步编程。

什么是异步编程?

同步编程中,方法是按顺序执行一个任务。如果一个函数依赖于另一个函数的输出,它必须等待该函数执行完毕。程序在执行该函数期间实际上停止了。这意味着一次只能执行一个程序。

这会降低程序的执行速度,因为它被迫停下来等待某事完成。系统中有许多处理器,因此在等待时执行其他任务而不是让其空闲是资源的浪费。

为了克服这一问题,引入了异步编程的概念。它的行为不同;它也一次只执行一个任务。但系统不会等待执行完成后再继续下一步。

这意味着处理器不会空闲,如果程序还没有完成运行而在其他地方运行。

在本教程中,我们将解释为什么需要这种类型的编程。

什么是 asyncio - 异步 I/O?

asyncio 是一个用于使用 async/await 运行并发代码的 Python 库。它是 Python 异步框架的基础,提供连接库、网络和 Web 服务器、分布式任务队列、高性能等功能。

该模块提供了围绕事件循环工作的框架,还负责 I/O 和系统事件等方面的处理。

协程和任务

asyncio 是一个用于使用 async/await 运行并发代码的 Python 库。它是 Python 异步框架的基础,提供连接库、网络、Web 服务器、数据库分布式任务队列、高性能等功能。

该模块提供了围绕事件循环工作并处理 I/O 和系统事件等方面的框架。

示例 - 1

import asyncio  
async def main():  
    print ("Waiting 5 seconds. ")  
    for _ in range(5):  
        await asyncio.sleep(1)  
        print ("Hello")  
    print ("Finished waiting.")  
asyncio.run(main())  

输出:

Waiting 5 seconds. 
Hello
Hello
Hello
Hello
Hello
Finished waiting.

说明 -

在上面的代码中:

  • 我们导入 asyncio 模块以获得 Python 的 async 功能。
  • 然后创建了一个 main() 函数,并在其前面加上了 async 关键字。这将允许程序以异步方式运行任务。
  • 我们使用 for 循环并调用 sleep() 方法,它强制我们等待 1 秒。
  • 程序在一秒后打印 "你好"。
  • 程序应该有一个 .run() 函数以及一个 .main() 函数。

我们还可以安排任务或对象来绑定协程并帮助它们运行。让我们理解以下示例。

示例 - 2

import asyncio  
import time  
  
async def execute(delay, value):  
    await asyncio.sleep(delay)  
    print(value)  
  
async def main():  
    print(f"started at {time.strftime('%X')}")  
  
    await execute(1, 'hello')  
    await execute(2, 'world')  
  
    print(f"finished at {time.strftime('%X')}")  
  
asyncio.run(main())  

输出:

started at 11:11:54
hello
world
finished at 11:11:57

说明 -

在上面的代码中:

  • 我们导入了 asyncio 和 time 模块。
  • 然后我们定义了 execute() 函数,带有延迟和值参数。它使用 sleep() 方法打印延迟时间。
  • main() 函数中,我们传递了两个参数:第一个是延迟时间,第二个是要打印的值。
  • 程序开始执行,并打印确切的执行时间,然后打印 '你好',然后等待两秒,打印 '世界',然后停止。

现在,让我们对上面的代码进行一些更改并查看结果。

示例 - 3 创建任务

async def execute(delay, value):  
    await asyncio.sleep(delay)  
    print(value)  
  
async def main():  
    # Using asyncio.create_task() method to run coroutines concurrently as asyncio  
    task1 = asyncio.create_task(  
        execute(1, 'hello'))  
  
    task2 = asyncio.create_task(  
        execute(2, 'world'))  
  
    print(f"started at {time.strftime('%X')}")  
  
    # Wait until both tasks are completed (should take  
    # around 2 seconds.)  
    await task1  
    await task2  
  
    print(f"finished at {time.strftime('%X')}")  
  
asyncio.run(main())  

输出:

started at 15:43:30
hello
world
finished at 15:43:32

我们可以看到它比前一个程序快 1 秒。create.task() 方法将在事件循环中运行,并将其结果放入任务中。我们已经安排了两个任务,并使用 await 返回它们。

在 Python 中管理异步事件循环

Asyncio 也用于管理异步事件循环。事件循环是一个运行异步函数和回调的对象。当我们想要执行协程时,事件很重要,当我们运行 asyncio.run() 方法时,事件循环对象会自动创建。要实现更高级的服务器,我们需要更低级的事件循环访问。我们需要直接处理事件循环的内部。

事件循环具有以下功能。

  • 它可以注册、执行和取消延迟调用(异步函数)
  • 它可以为通信创建客户端和服务器传输
  • 它可以创建用于与另一个程序通信的子进程和传输。
  • 将函数调用委派给线程池。

让我们看看以下示例。

示例 -

import asyncio  
  
async def speech_async():  
    print('This is a asynchronicity!')  
  
loop = asyncio.get_event_loop()  
loop.run_until_complete(speech_async())  
loop.close()  

输出:

This is a asynchronicity!

事件循环通过获取 asyncio.get_event_loop() 开始,安排并运行异步任务,然后在运行结束后关闭事件循环。

用 Python 中的 Stream 读写数据

asyncio 模块提供了用于执行高级网络 I/O 的 stream,它可以用作网络请求的服务器。它最适合长时间运行的网络操作,在该操作中,应用程序会阻塞等待其他资源返回结果。

asyncio 有两个类,StreamReader 和 StreamWriter,这些类用于高级网络读取和写入。要从网络读取,我们需要使用 asyncio.open_connection() 打开网络。StreamReaderStreamWriter 对象函数返回元组,我们可以使用 .read() 和 .write() 方法对每个连接进行操作。

asyncio.start_server() 方法用于接收来自远程主机的连接。此函数需要回调函数 client_connected_cb 作为参数。每当函数接收到请求时,都会调用它。

在 Python 中同步任务

如前所述,异步程序运行独立,但有时我们希望它们互相通信。asyncio 模块为我们提供了队列和各种其他方法来建立任务之间的同步。

让我们了解以下实现方法。

  • 队列 - asyncio 队列可使异步函数排队以由其他异步函数使用。例如 - 工作负载分布在函数上,以根据其行为进行分配。
  • 同步原语 - asyncio 的功能锁、事件、条件和信号量等行为类似于常规的 Python 对应物。

这里应该始终记住这些方法不是线程安全的。这对于在同一事件循环中运行的异步任务不是问题。但我们需要使用线程模块在任务之间共享信息。

何时使用异步编程?

在以下情况下,我们可以使用异步编程。

  • 当我们希望在较短的时间内完成工作。
  • 延迟涉及等待 I/O(磁盘或网络)操作,而不涉及计算。
  • 当许多 I/O 操作同时发生时。

asyncio 模块允许我们并行执行多个任务并高效地迭代它们,而不会阻塞应用程序的其余部分。

以下是一些适合使用 asyncio 的任务。

  • 网页抓取。
  • 网络服务(Web 服务器和框架)
  • 并发数据库

异步编程中的一些重要函数

以下是在进行异步编程时使用的一些重要方法。

运行 asyncio 程序

  • asyncio.run(coro, *, debug = False) - 此函数用于阻塞执行 delay 秒。它挂起当前任务并允许其他任务运行。delay 是一个参数,表示秒数。

示例 -

async def main():  
    await asyncio.sleep(1)  
    print('hello')  
asyncio.run(main())  

创建任务

  • create_task(coro, *, name = None) - 此函数将协程包装成任务,并调度其执行。它返回任务对象。

示例 -

async def coro():  
    ...  
  
# In Python 3.7+  
task = asyncio.create_task(coro())  
...  
task = asyncio.ensure_future(coro())  

等待

  • sleep(delay, result = None, *, loop = None) - 此函数用于阻塞执行 delay 秒。它挂起当前任务并允许其他任务运行。delay 是一个参数,表示秒数。

示例 -

import asyncio  
async def main():  
    for _ in range(3):  
        await asyncio.sleep(1)  
        print ("Hello")  
asyncio.run(main())  

超时

  • coroutinewait_for(aw, timeout, *, loop = None) - 此函数用于等待 aw(协程自动调度为任务)的完成,带有超时。

示例 -

async def myfunc():  
    # Sleep for ten minutes  
    await asyncio.sleep(600)  
    print('hello!')  
  
async def main():  
    # Wait for at most 1 second  
    try:  
        await asyncio.wait_for(myfunc(), timeout=1.0)  
    except asyncio.TimeoutError:  
        print('timeout!')  
  
asyncio.run(main())  

结论

本教程介绍了使用 Python asyncio 模块进行异步编程的概念。asyncio 允许我们在使用上下文切换时对程序进行编程控制。这意味着我们可以处理许多与线程编程相关的复杂问题。

它是一个强大而有价值的工具,但只适用于异步类型的编程。我们已经讨论了协程和任务以及它们各自的示例。我们还讨论了如何管理事件循环以及在 Python 中读写数据流的内容。还包括了一些重要的方法。

标签: Tkinter教程, Tkinter安装, Tkinter库, Tkinter入门, Tkinter学习, Tkinter入门教程, Tkinter, Tkinter进阶, Tkinter指南, Tkinter学习指南, Tkinter进阶教程, Tkinter编程