未提供项目描述
项目描述
quattro: asyncio任务控制
quattro是一个Apache 2许可证的库,用Python编写,用于asyncio应用程序中的任务控制。quattro受到来自Trio框架的结构化并发概念的启发。
quattro支持Python版本3.9 - 3.11,包括PyPy。
安装
要安装quattro,只需
$ pip install quattro
quattro.gather
quattro提供了一个基于任务组的独立、简单的asyncio.gather
实现。与子任务中的错误相比,quattro版本更安全,并且在后台使用任务组以防止任务泄露。
from quattro import gather
async def my_handler():
res_1, res_2 = await gather(long_query_1(), long_query_2())
可以使用return_exceptions
参数来使用gather()
捕获并返回异常作为响应,而不是让它们冒泡出去。
from quattro import gather
async def my_handler():
res_1, res_2 = await gather(
long_query_1(),
long_query_2(),
return_exceptions=True,
)
# res_1 and res_2 may be instances of exceptions.
quattro.gather()
与asyncio.gather()
的区别在于
- 如果一个子任务失败,其他未完成的任务将被取消,就像在TaskGroup中一样。
quattro.gather()
仅接受协程,不接受未来和生成器,就像TaskGroup一样。- 当
return_exceptions
为假(默认值)时,子任务中的异常将导致ExceptionGroup从顶级gather()
调用中冒泡出来,就像在TaskGroup中一样。 - 结果以元组的形式返回,而不是列表。
取消作用域
quattro包含了一个独立的、基于asyncio的Trio CancelScopes实现。由于asyncio和Trio之间的基本差异,实际的运行时行为并不完全相同,但很接近。
from quattro import move_on_after
async def my_handler():
with move_on_after(1.0) as cancel_scope:
await long_query()
# 1 second later, the function continues running
quattro 包含以下辅助器:
move_on_after
move_on_at
fail_after
fail_at
所有辅助器都生成 quattro.CancelScope
实例,它与 Trio 变体非常相似。
CancelScopes
具有以下属性:
cancel()
- 一个可以手动取消作用域的方法。在进入作用域之前可以调用cancel()
;进入作用域时将在第一个机会取消它deadline
- 读写,作用域的可选截止日期,在该日期作用域将被取消cancelled_caught
- 一个只读 bool 属性,表示作用域是否通过取消完成
quattro 还支持使用 quattro.current_effective_deadline
在任务中检索当前有效截止日期。当前有效截止日期是一个浮点值,其中 float('inf')
表示没有截止日期。
Python 3.11 及更高版本包含类似的辅助器 asyncio.timeout 和 asyncio.timeout_at。quattro 的 fail_after
和 fail_at
辅助器实际上等同于 asyncio 超时,并且通过了它们的测试套件。
区别在于:
- quattro 版本是普通上下文管理器(仅使用
with
),asyncio 版本是异步上下文管理器(使用async with
)。两个版本都不需要是异步的,因为没有等待;quattro 选择非异步以表示没有遇到挂起点,与 Trio 保持一致,并且更易读。 - quattro 还包含
move_on_at
和move_on_after
辅助器。 - quattro 版本支持获取当前有效截止日期。
- quattro 版本可以使用
scope.cancel()
手动取消,并在进入之前预先取消。 - quattro 版本在所有支持的 Python 版本中均可用,而不仅仅是 3.11+。
asyncio 和 Trio 的区别:
当它们失败时,fail_after
和 fail_at
抛出 asyncio.Timeout
异常而不是 trio.Cancelled
异常。
asyncio 使用边沿触发取消语义,而 Trio 使用电平触发取消语义。以下示例在 quattro 和 Trio 中的行为将不同
with trio.move_on_after(TIMEOUT):
conn = make_connection()
try:
await conn.send_hello_msg()
finally:
await conn.send_goodbye_msg()
在 Trio 中,如果 TIMEOUT
在等待 send_hello_msg()
时过期,则还会取消 send_goodbye_msg()
。在 quattro 中,send_goodbye_msg()
仍然会运行(并可能阻塞)。这是底层框架的限制。
在 quattro 中,取消作用域无法被屏蔽。
任务组
在 Python 3.11 及更高版本上,使用标准库 TaskGroup 实现。这里的 TaskGroup 实现可以被视为旧版 Python 版本的移植。
quattro 包含一个 TaskGroup 实现。TaskGroups 受 Trio nurseries 的启发。
from quattro import TaskGroup
async def my_handler():
# We want to spawn some tasks, and ensure they are all handled before we return.
async def task_1():
...
async def task_2():
...
async with TaskGroup() as tg:
t1 = tg.create_task(task_1)
t2 = tg.create_task(task_2)
# The end of the `async with` block awaits the tasks, ensuring they are handled.
TaskGroups 是实现 结构化并发 的基本构建块。简单来说,结构化并发意味着你的代码不会泄漏任务 - 当协程完成时,该协程生成的所有任务及其所有子任务也将完成。(用时髦的话说,执行流程成为一个有向无环图。)
可以使用 TaskGroups 代替 asyncio.create_task
来启动后台任务来实现结构化并发。TaskGroups 实际上做了两件事
- 当退出 TaskGroup 的
async with
块时,TaskGroup 等待所有子任务,确保它们在退出时已完成 - 当 TaskGroup 子任务引发异常时,所有其他子任务和上下文管理器内的任务将被取消
实现已从EdgeDB项目借用。
变更日志
24.1.0 (2024-05-01)
- 添加Trove分类器。
- 将
name
关键字参数添加到TaskGroup.create_task
。(#8)
23.1.0 (2023-11-29)
22.2.0 (2022-12-27)
- 3.11上的嵌套取消操作更健壮。
- 对
fail_after
和fail_at
提供更好的类型支持。 - 改进已取消作用域的截止日期处理。
- TaskGroups现在在创建任务时支持自定义ContextVar上下文,就像标准库实现一样。
22.1.0 (2022-12-19)
- 恢复TaskGroup版权声明。
- TaskGroups现在在子错误上抛出ExceptionGroups(在必要时使用PyPI回滚版)。
- 添加对Python 3.11的支持,弃用3.8。
- TaskGroups不再有
name
,且repr
略有不同,以与Python 3.11标准库实现保持一致。 - TaskGroups在终止时不再吞并子异常,以与Python 3.11标准库实现保持一致。
- 切换到CalVer。
0.3.0 (2022-01-08)
- 添加
py.typed
以启用类型信息。 - 完善TaskGroups的类型注释。
0.2.0 (2021-12-27)
- 添加
quattro.current_effective_deadline
。
0.1.0 (2021-12-08)
- 首次发布,包含任务组和取消作用域。
致谢
初始TaskGroup实现来自EdgeDB项目。CancelScope实现受到Trio的极大影响,并受到async_timeout包的启发。
项目详情
下载文件
下载适用于您平台的文件。如果您不确定要选择哪个,请了解更多关于安装包的信息。
源分布
构建分布
quattro-24.1.0.tar.gz的哈希
算法 | 哈希摘要 | |
---|---|---|
SHA256 | ec1299f95ea6688c5026fefd3d34b1cdc9fab9932d34b940374d3f6bbcb02415 |
|
MD5 | f69d4082e7ffac1baf91341ccbc7826d |
|
BLAKE2b-256 | e8572c5555ccf6b9e63193c124c686e18a5b0afb36a36017369ca581b608e087 |
quattro-24.1.0-py3-none-any.whl的哈希
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 0bfbccb71eeb121110efc989165d556cced1e1559c6b078819a8b17ea49f7861 |
|
MD5 | 6a58c4fd9459bf38b152e2e65d2644b5 |
|
BLAKE2b-256 | 9d2d90dcec43cb8220bfc30abcd09306e96c0fe9380ac122e18858fb3c7462b4 |