Python异步编程:asyncio库的使用和实践

云端之上 2020-05-20 ⋅ 44 阅读

引言

在传统的同步编程模型中,代码是按照顺序执行的,当遇到IO操作或者其他耗时操作时,程序会被阻塞,直到操作完成才能继续执行下一步。而在异步编程模型中,程序可以在遇到IO操作时,将其委托给其他任务来处理,并继续执行后续的操作,从而提高了程序的效率和响应能力。

Python提供了asyncio库,它是用于编写异步代码的标准库。本文将介绍asyncio库的基本概念和使用方法,并通过实例演示如何在Python中进行异步编程。

asyncio库的基本概念

协程(Coroutines)

在异步编程中,协程是一个可以暂停和恢复的函数。通过使用async关键字定义的函数可以被视为协程。协程可以在遇到await语句时暂停执行,并将控制权交给事件循环(Event Loop),直到等待的操作完成。

事件循环(Event Loop)

事件循环是异步程序的核心组件,它负责调度和协调协程的执行。事件循环可以将任务放入任务队列中,并根据任务的状态和优先级进行调度。当一个协程被暂停时,事件循环会从队列中取出下一个可执行的协程,并将控制权交给它。

Future对象

Future对象是异步操作的结果,它代表了一个协程或线程的执行状态。Future对象可以用来获取异步操作的结果,或者在操作完成时执行回调。

asyncio库的使用

创建一个事件循环

使用asyncio.get_event_loop()函数可以获取一个事件循环对象。

import asyncio

loop = asyncio.get_event_loop()

定义一个协程

使用async关键字定义一个协程。

import asyncio

async def my_coroutine():
    await asyncio.sleep(1)
    print("Hello, world!")

执行协程

使用loop.run_until_complete()函数来运行一个协程。

import asyncio

async def my_coroutine():
    await asyncio.sleep(1)
    print("Hello, world!")

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

并发执行多个协程

使用asyncio.gather()函数可以并发执行多个协程。

import asyncio

async def coroutine1():
    await asyncio.sleep(1)
    print("Coroutine 1")

async def coroutine2():
    await asyncio.sleep(2)
    print("Coroutine 2")

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(coroutine1(), coroutine2()))

异步IO操作

使用asyncio.open_connection()函数可以进行异步的网络连接。

import asyncio

async def download_data():
    reader, writer = await asyncio.open_connection('example.com', 80)
    writer.write(b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")
    await writer.drain()
    data = await reader.read()
    print(data.decode())
    writer.close()
    await writer.wait_closed()

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

添加回调函数

使用add_done_callback()方法可以为Future对象添加回调函数。

import asyncio

def callback(future):
    print("Task done!")

async def my_coroutine():
    await asyncio.sleep(1)
    return "Hello, world!"

loop = asyncio.get_event_loop()
task = loop.create_task(my_coroutine())
task.add_done_callback(callback)
loop.run_until_complete(task)

实践:使用asyncio实现一个简单的Web服务器

下面是一个使用asyncio库实现的简单Web服务器代码示例。当有请求到达时,服务器会返回一个简单的HTML页面。

import asyncio

async def handle_request(reader, writer):
    request = await reader.read()
    print(request.decode())
    response = b"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<html><body><h1>Hello, world!</h1></body></html>"
    writer.write(response)
    await writer.drain()
    writer.close()

async def main():
    server = await asyncio.start_server(handle_request, '127.0.0.1', 8080)
    print(f"Serving on {server.sockets[0].getsockname()}")
    async with server:
        await server.serve_forever()

asyncio.run(main())

通过运行上述代码,你可以在本地的8080端口上启动一个简单的Web服务器。当在浏览器中访问http://localhost:8080时,将会看到一个显示"Hello, world!"的页面。

总结

Python的asyncio库提供了一套强大的工具和机制,用于编写高效的异步代码。通过使用async关键字定义协程,并利用事件循环和Future对象来协调协程的执行,我们可以轻松地实现并发和异步IO操作。希望本文对你理解和使用asyncio库有所帮助!

参考资料:


全部评论: 0

    我有话说: