Python 将中间函数实现为协同路由或返回可等待项
有两种实现中间函数的方法,它们位于Python 将中间函数实现为协同路由或返回可等待项,python,python-asyncio,Python,Python Asyncio,有两种实现中间函数的方法,它们位于可等待的创建和对象被等待的站点之间。一种实现使中间函数成为协同程序,其中可等待被等待等待;然后,用户在该协同程序上等待。另一种方法是将中间步骤编写为函数,创建Awaitable,并将其返回到发生await的站点。下面是一个例子 导入异步IO 从键入导入等待 异步def wait1()->无: 等待asyncio.sleep(1) def wait2()->可等待[无]: 返回asyncio.sleep(1) 异步def main(): 等待wait1() 等待等
可等待
的创建和对象被等待
的站点之间。一种实现使中间函数成为协同程序,其中可等待
被等待
等待;然后,用户在该协同程序上等待。另一种方法是将中间步骤编写为函数,创建Awaitable
,并将其返回到发生await
的站点。下面是一个例子
导入异步IO
从键入导入等待
异步def wait1()->无:
等待asyncio.sleep(1)
def wait2()->可等待[无]:
返回asyncio.sleep(1)
异步def main():
等待wait1()
等待等待2()
asyncio.run(main())
这两种实现之间有什么区别?利与弊?性能差异?有没有行为上的差异?我正在制作许多这样的函数,并且希望做“正确”的事情。目前使用的,
wait1
和wait2
在功能上是等效的。调用时,两者都返回一个协同路由对象,即运行异步(协同路由)函数的结果。如果出现以下情况,则会产生差异:
- 这些功能有副作用,并且
- 他们返回的等待时间不是立即等待的
wait1
而言,副作用只有在等待之后才会发生,而对于wait2
而言,副作用将在调用后立即发生
在大多数情况下,这没有什么区别,但有时是可以观察到的。例如,函数run_in_executor
不能作为协同程序实现,因为当前实现是一个函数,它首先将接收到的可调用内容提交给执行器,然后创建并返回一个代理底层的。这允许API用户编写:
#我不在乎结果,只要提交就行了
loop.run_in_executor(无,我的_回调)
如果run\u in\u executor
是一个协同程序,这将是不可操作的,在您等待它或将它传递给create\u task
以运行它之前,不会提交任何内容
我正在做很多这样的功能,我想做“正确”的事情
为了清晰起见,我会尽可能使用协同程序。在不能使用协同程序的地方,比如lambda表达式,可以使用
wait1
和wait2
之间的等价性。正如当前使用的那样,wait1
和wait2
在功能上是等价的。调用时,两者都返回一个协同路由对象,即运行异步(协同路由)函数的结果。如果出现以下情况,则会产生差异:
- 这些功能有副作用,并且
- 他们返回的等待时间不是立即等待的
wait1
而言,副作用只有在等待之后才会发生,而对于wait2
而言,副作用将在调用后立即发生
在大多数情况下,这没有什么区别,但有时是可以观察到的。例如,函数run_in_executor
不能作为协同程序实现,因为当前实现是一个函数,它首先将接收到的可调用内容提交给执行器,然后创建并返回一个代理底层的。这允许API用户编写:
#我不在乎结果,只要提交就行了
loop.run_in_executor(无,我的_回调)
如果run\u in\u executor
是一个协同程序,这将是不可操作的,在您等待它或将它传递给create\u task
以运行它之前,不会提交任何内容
我正在做很多这样的功能,我想做“正确”的事情
为了清晰起见,我会尽可能使用协同程序。在不能使用协程的地方,比如lambda表达式,可以使用wait1
和wait2
之间的等价性