使用pytest-fixtures风格的依赖注入运行异步工作流程
项目描述
asyncinject
使用pytest-fixtures风格的依赖注入运行异步工作流程
安装
使用pip
安装此库
$ pip install asyncinject
用法
此库受pytest fixtures的启发。
想法是通过允许使用一组函数定义它们,其中函数参数表示需要首先执行的依赖函数来简化执行并行asyncio
操作。
然后库可以创建并执行一个计划,以尽可能有效的顺序并行执行所需的函数。
以下是一个示例,使用httpx HTTP库。
from asyncinject import Registry
import httpx
async def get(url):
async with httpx.AsyncClient() as client:
return (await client.get(url)).text
async def example():
return await get("http://www.example.com/")
async def simonwillison():
return await get("https://simonwillison.net/search/?tag=empty")
async def both(example, simonwillison):
return example + "\n\n" + simonwillison
registry = Registry(example, simonwillison, both)
combined = await registry.resolve(both)
print(combined)
如果您在ipython
或python -m asyncio
(在控制台中启用顶级await)中运行此代码,您将看到结合了两个页面HTML的输出。
将对www.example.com
和simonwillison.net
的HTTP请求并行执行。
库会注意到both()
接受两个参数,这两个参数是其他注册的async def
函数的名称,并将构建一个执行计划,该计划并行执行这两个函数,然后将它们的输出传递给both()
方法。
Registry.from_dict()
将函数列表传递给Registry
构造函数将为每个函数注册其内省的函数名,使用fn.__name__
。
您可以使用字典设置显式的名称
registry = Registry.from_dict({
"example": example,
"simonwillison": simonwillison,
"both": both
})
这些字符串名称将用于匹配参数,因此每个函数都需要接受以该字典中使用的键命名的参数。
注册其他函数
可以注册的函数可以是常规函数或async def
函数。
除了通过构造函数传递函数来注册函数外,您还可以使用 .register()
方法将它们添加到注册表中
async def another():
return "another"
registry.register(another)
要使用除函数名称以外的名称进行注册,请传递 name=
参数
async def another():
return "another 2"
registry.register(another, name="another_2")
解决未注册的函数
您不需要注册传递给 .resolve()
的最终函数 - 如果传递未注册的函数,库将直接 introspect 函数的参数并解决它们。
这对常规和异步函数都有效
async def one():
return 1
async def two():
return 2
registry = Registry(one, two)
# async def works here too:
def three(one, two):
return one + two
print(await registry.resolve(three))
# Prints 3
参数会传递下去
您的依赖函数可以要求传递给 .resolve()
调用的关键字参数
async def get_param_1(param1):
return await get(param1)
async def get_param_2(param2):
return await get(param2)
async def both(get_param_1, get_param_2):
return get_param_1 + "\n\n" + get_param_2
combined = await Registry(get_param_1, get_param_2, both).resolve(
both,
param1 = "http://www.example.com/",
param2 = "https://simonwillison.net/search/?tag=empty"
)
print(combined)
具有默认值的参数将被忽略
您可以通过为参数分配默认值来将其排除在依赖注入机制之外
async def go(calc1, x=5):
return calc1 + x
async def calc1():
return 5
print(await Registry(calc1, go).resolve(go))
# Prints 10
使用计时器进行跟踪
您可以将一个 timer=
可调用对象传递给 Registry
构造函数以收集关于执行任务的时间信息。您的函数应接受三个位置参数
name
- 正在被计时的函数的名称start
- 它开始执行的时间,使用time.perf_counter()
(perf_counter() 文档)end
- 它完成执行的时间
您也可以在这里使用 print
combined = await Registry(
get_param_1, get_param_2, both, timer=print
).resolve(
both,
param1 = "http://www.example.com/",
param2 = "https://simonwillison.net/search/?tag=empty"
)
这将输出
get_param_1 436633.584580685 436633.797921747
get_param_2 436633.641832699 436634.196364347
both 436634.196570217 436634.196575639
关闭并行执行
默认情况下,根据执行计划可以并行运行的函数将使用 asyncio.gather()
并行运行。
您可以通过将 parallel=False
传递给 Registry
构造函数或在创建注册表对象后设置 registry.parallel = False
来禁用此并行执行。
这主要用于比较您项目的并行和顺序执行之间的差异。
开发
要为此库做出贡献,首先检出代码。然后创建一个新的虚拟环境
cd asyncinject
python -m venv venv
source venv/bin/activate
现在安装依赖项并测试依赖项
pip install -e '.[test]'
要运行测试
pytest
项目详情
下载文件
下载适用于您的平台的文件。如果您不确定要选择哪一个,请了解更多关于 安装包 的信息。
源分布
构建分布
asyncinject-0.6.tar.gz 的散列值
算法 | 散列摘要 | |
---|---|---|
SHA256 | ee8e879e3c18eaa5fd0b6962ac447ee80f21b201f5d12986f59fa6e0638ba774 |
|
MD5 | 8412d6066226d30a550a7ac08cc798e3 |
|
BLAKE2b-256 | e26962b417803ee72f9cd5d159e52b29067c57f8a5260493ea90ff402e4be056 |