fastapi 是一个异步的web框架。
Starlette 是一个轻量级、快速的 Python ASGI 框架,专为构建高性能异步 Web 应用和微服务而设计。它是 FastAPI 的核心依赖之一,许多 FastAPI 的功能都基于 Starlette 提供的组件。Starlette 以其简洁的设计和丰富的功能而著称,非常适合构建现代异步 Web 应用。
uvicorn 是一个快速、轻量级的 Python ASGI(Asynchronous Server Gateway Interface)服务器,专为运行高性能的异步 Web 应用和框架而设计。uvicorn 是使用 uvloop 和 httptools 构建的,这使它在处理 HTTP 请求时表现出色,尤其适用于基于异步 I/O 的应用。
uvloop 是一个用于 Python 的高性能事件循环,它是 asyncio 的一个替代实现。uvloop 是基于 libuv 构建的,libuv 是一个跨平台的异步 I/O 库,广泛用于 Node.js 和其他异步系统中。
fastapi的ASGI服务器是可选的,一般会选择uvicorn。
uvicorn的事件循环也是可选的,一般默认使用asyncio默认的事件循环,也可以设置为uvloop。
事件循环:
- 单线程:在单个线程中只能有一个活动的事件循环。
- 多线程:你可以在不同的线程中创建和运行各自的事件循环,但每个线程只能有一个事件循环在运行。
asyncio.get_event_loop():
用于获取当前线程的事件循环。如果不存在,则创建并返回一个新的。
适合主线程中的异步任务启动或管理。
asyncio.get_running_loop():
用于获取当前正在运行的事件循环。如果没有运行的事件循环则抛出错误。
适合在已经运行的协程或回调函数中使用。
asyncio.new_event_loop():
总是创建并返回一个新的事件循环实例,不会自动设置为当前线程的事件循环。
适合需要手动管理事件循环的场景,特别是在多线程或测试环境中。
windows系统事件循环策略: asyncio模块使用的windows系统的默认的事件循环策略。
asyncio.WindowsSelectorEventLoopPolicy: Python 3.7 及之前的版本
asyncio.WindowsProactorEventLoopPolicy: Python 3.8 及之后的版本
uvloop.EventLoopPolicy(): uvloop自己的事件循环策略
有时候,可能是一些库WindowsProactorEventLoopPolicy支持的不好,在使用asyncio.run()运行异步函数时经常报event loop is closed这样的错误,这时可以考虑改变事件循环策略。
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
或者使用旧的方式运行异步函数:
loop = asyncio.get_event_loop()
loop.run_until_complete(fun())
事件循环的创建:
asyncio.run()函数会自动创建一个事件循环
像web框架,比如fastapi,会在服务器启动时自动创建一个事件循环。
uvicorn.run(f"{app_model_name}:app", host='0.0.0.0', reload=False)
在单线程中,可以使用asyncio.get_event_loop()来创建。
在多线程中,一般在子线程中使用asyncio.new_event_loop()来创建子线程自已的事件循环。
当你明确知道代码是在事件循环中运行时,可以用asyncio.get_running_loop()方法获取当前运行的事件循环, 一般用于异步函数内部。
下面是一个在子线程中使用事件循环的示例:
import asyncio
import threading
async def hello():
print(f"Hello from thread {threading.current_thread().name}")
await asyncio.sleep(1)
print(f"Goodbye from thread {threading.current_thread().name}")
def start_loop():
loop = asyncio.new_event_loop() # 创建一个新的事件循环
asyncio.set_event_loop(loop) # 设置为当前线程的事件循环
loop.run_until_complete(hello())
# 在主线程中运行一个事件循环
asyncio.run(hello())
# 在一个子线程中运行另一个事件循环
thread = threading.Thread(target=start_loop)
thread.start()
thread.join()
标签:异步,python,循环,线程,事件,loop,asyncio
From: https://www.cnblogs.com/rolandhe/p/18369810