python 5个顶级异步框架推荐

1. asyncio

asyncio是Python3.4中引入的异步编程库,提供了高效的异步I/O框架,可用于编写高性能的并发编程。其主要特点如下:

1.1 协程

asyncio基于协程(coroutine)编写,协程是一种用户态的轻量级线程,与操作系统的线程不同,协程之间的切换不需要切换到操作系统内核态,因此开销非常小。

下面的示例展示了使用asyncio编写的协程:

import asyncio

async def hello_world():

print("Hello World!")

loop = asyncio.get_event_loop()

loop.run_until_complete(hello_world())

在上面的代码中,定义了一个async函数hello_world,然后使用asyncio的get_event_loop方法获取一个事件循环loop,使用loop的run_until_complete方法执行hello_world协程。

1.2 异步I/O

asyncio提供了基于事件驱动的异步I/O框架,支持TCP、UDP、SSL/TLS、子进程等协议和功能。

下面的示例展示了如何使用asyncio实现一个简单的TCP服务器:

import asyncio

async def handle_echo(reader, writer):

data = await reader.read(100)

message = data.decode()

addr = writer.get_extra_info('peername')

print(f"Received {message} from {addr!r}")

print(f"Send: {message!r}")

writer.write(data)

await writer.drain()

print("Close the connection")

writer.close()

async def main():

server = await asyncio.start_server(handle_echo, '127.0.0.1', 8888)

addr = server.sockets[0].getsockname()

print(f"Serving on {addr}")

async with server:

await server.serve_forever()

asyncio.run(main())

在上面的代码中,定义了一个handle_echo协程,该协程处理接收到的客户端请求。main协程创建一个TCP服务器,监听本地地址127.0.0.1和端口8888。当有一个客户端连接时,handle_echo协程会被调用来处理该客户端的请求。

2. trio

trio是一个基于async/await的异步I/O库,专注于简化异步编程的复杂性,使得编写正确的并发代码更容易、更自然、更高效。

2.1 Nurseries

trio使用Nursery来管理协程,它类似于Python的with语句,可以同时管理多个协程,保证所有协程正常运行和关闭:

import trio

async def child1():

print('child1 started')

await trio.sleep(1)

print('child1 ended')

async def child2():

print('child2 started')

await trio.sleep(2)

print('child2 ended')

async def parent():

async with trio.open_nursery() as nursery:

nursery.start_soon(child1)

nursery.start_soon(child2)

trio.run(parent)

上面的代码中,child1和child2为子协程,parent为父协程,通过使用open_nursery方法创建一个nursery,然后使用start_soon方法向该nursery中添加子协程,最后使用trio.run方法来运行父协程。

2.2 Cancel Scopes

trio中的协程可以被取消,当一个协程被取消时,其所有的嵌套协程也会被取消。trio中的取消机制是通过cancel_scope实现的。

import trio

async def child1():

try:

while True:

print('child1')

await trio.sleep(1)

except trio.Cancelled:

print('child1 cancelled')

async def child2():

try:

while True:

print('child2')

await trio.sleep(1)

except trio.Cancelled:

print('child2 cancelled')

async def parent():

async with trio.open_nursery() as nursery:

nursery.start_soon(child1)

nursery.start_soon(child2)

await trio.sleep(3)

nursery.cancel_scope.cancel()

trio.run(parent)

上面的代码中,当父协程(parent)运行了3秒时,就会取消所有嵌套在该协程中的子协程(child1和child2)。

3. curio

curio是一个异步I/O库,它使用async/await语法,提供了面向对象的并发模型,可以简化异步编程的复杂性。

3.1 Task

curio中的Task类封装了一个可以运行的协程,可以使用它来启动、取消以及等待协程的执行。

import curio

async def my_coro():

await curio.sleep(1)

return 'result'

async def main():

task = await curio.spawn(my_coro)

result = await task.join()

print(result)

curio.run(main)

上面的代码中,定义了一个my_coro协程,它会在1秒后返回'result'。main协程创建一个Task对象来启动my_coro协程,并使用Task对象的join方法来等待协程执行完毕并获取其返回值。

3.2 Queue

curio中的Queue类是线程安全的,可以用来在协程之间安全地传递数据,在代码中使用Queue时需要小心,以避免死锁。

import curio

async def sender(queue):

for i in range(5):

await queue.put(i)

async def receiver(queue):

while True:

value = await queue.get()

print(value)

async def main():

queue = curio.Queue()

tasks = [

await curio.spawn(sender, queue),

await curio.spawn(receiver, queue)

]

await curio.gather(*tasks)

curio.run(main)

上面的代码中,sender协程向队列中放入5个数值,receiver协程从队列中获取数值并输出。在main协程中,创建了一个Queue对象,并使用gather方法同时启动了sender和receiver协程。

4. uvloop

uvloop是一个高性能Python异步I/O库,它使用Cython构建,基于libuv库实现,提供了比标准的asyncio库更高的性能。

4.1 Loop

uvloop使用uvloop.Loop来创建事件循环,它与asyncio的Loop对象具有完全相同的API,并提供了更高的性能和更低的延迟。

import asyncio

import uvloop

async def hello_world():

print("Hello World!")

asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())

loop = asyncio.get_event_loop()

loop.run_until_complete(hello_world())

上面的代码中,使用uvloop库创建了uvloop的事件循环,并使用asyncio的set_event_loop_policy方法将uvloop设置为默认的事件循环实现,然后使用get_event_loop方法获取事件循环并运行hello_world协程。

4.2 TCP

uvloop提供了TCPServer和TCPClient类,可用于创建高性能的TCP服务器和客户端。

import uvloop

import asyncio

async def handle_echo(reader, writer):

data = await reader.read(100)

message = data.decode()

addr = writer.get_extra_info('peername')

print(f"Received {message} from {addr!r}")

print(f"Send: {message!r}")

writer.write(data)

await writer.drain()

print("Close the connection")

writer.close()

async def main():

server = await asyncio.start_server(handle_echo, '127.0.0.1', 8888)

async with server:

await server.serve_forever()

asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())

asyncio.run(main())

上面的代码是一个使用uvloop实现的TCP服务器示例,与asyncio的实现很相似,在main协程中使用asyncio的start_server方法创建一个TCP服务器,并使用server_forever方法开始监听来自客户端的请求。

5. trio_asyncio

trio-asyncio是一个异步I/O库,它提供了一个trio.EventLoopPolicy类,可以将asyncio的事件循环嵌入到trio应用程序中。

5.1 TrioPolicy

trio_asyncio提供了一个TrioPolicy类,实现了一个asyncio的事件循环 policy,可以将其设置为默认的policy,允许在trio中使用asyncio异步I/O。

import asyncio

import trio

import trio_asyncio

async def hello_world():

print("Hello World!")

async def main():

policy = trio_asyncio.TrioPolicy()

asyncio.set_event_loop_policy(policy)

loop = asyncio.get_event_loop()

loop.set_default_executor(trio_asyncio.AsyncioExecutor())

await trio.to_thread.run_asyncio(loop.run_until_complete, hello_world())

trio.run(main)

上面的代码中,使用trio_asyncio的TrioPolicy将异步I/O库asyncio的事件循环嵌入到trio应用程序中,使用TrioPolicy创建一个事件循环,然后使用run_asyncio方法在trio的执行上下文中执行事件循环。

5.2 TrioSemaphore

trio_asyncio还提供了一个TrioSemaphore类,它是trio和asyncio之间的信号量,可以在trio和asyncio之间同步并发的访问。

import asyncio

import trio

import trio_asyncio

async def async_fn():

async with trio_asyncio.open_trio_semaphore(1) as sem:

await sem.acquire()

await asyncio.sleep(1)

sem.release()

async def main():

async with trio.open_nursery() as nursery:

for i in range(3):

nursery.start_soon(async_fn)

trio.run(main)

上面的代码中,首先在async_fn协程中创建了一个TrioSemaphore信号量,然后使用open_trio_semaphore方法创建了一个与asyncio关联的信号量,并使用nursery开启了几个dev协程,这些协程是运行在trio中,但能够与异步I/O库asyncio进行同步并发访问。

总结

Python中有很多高性能的异步I/O库,其中包括asyncio、trio、curio、uvloop以及trio_asyncio。这些库都以不同的方式提供了异步编程的支持,可以根据实际需求选择适合的库来开发高性能并发应用程序。

后端开发标签