在Python中,我通常会遇到这样一种情况:我有许多嵌套的3.5+,只是为了调用一个深度为协同的东西,在大多数函数中,await只是在尾部调用,如下所示:
import asyncio
async def deep(time):
await asyncio.sleep(time)
return time
async def c(time):
time *= 2
return await deep(time)
async def b(time):
time *= 2
return await c(time)
async def a(time):
time *= 2
return await b(time)
async def test():
print(await a(0.1))
loop = asyncio.get_event_loop()
loop.run_until_complete(test())
loop.close()这些函数a、b和c可以编写为返回协同线的正则函数,而不是作为协同线本身编写,如下所示:
import asyncio
async def deep(time):
await asyncio.sleep(time)
return time
def c(time):
time *= 2
return deep(time)
def b(time):
time *= 2
return c(time)
def a(time):
time *= 2
return b(time)
async def test():
print(await a(0.1))
loop = asyncio.get_event_loop()
loop.run_until_complete(test())
loop.close()哪条路更像毕多诺?哪条路更有表现力?对其他人来说,未来哪一种方式更容易维护?
编辑-性能测量
作为性能测试,我从await asyncio.sleep(time)中删除了deep行,并对await a(0.1)进行了1,000,000次迭代。在我使用CPython 3.5.2的测试系统上,第一个版本大约需要2.4秒,第二个版本大约需要1.6秒。所以看起来做任何事情都会有性能上的损失,但这肯定不是一个数量级。也许拥有更多经验的Python代码可以创建一个适当的基准,并最终解决性能问题。
发布于 2017-05-28 09:15:09
使用第一个:您不仅可以显式地显示代码可以挂起的位置(放置await的位置),还可以获得所有相关的好处,比如显示有帮助的执行流的跟踪。
要查看两者之间的差异,请更改您的deep协同值以抛出一些错误:
async def deep(time):
await asyncio.sleep(time)
raise ValueError('some error happened')
return time对于第一个片段,您将看到以下输出:
Traceback (most recent call last):
File ".\tmp.py", line 116, in <module>
loop.run_until_complete(test())
File ".\Python36\lib\asyncio\base_events.py", line 466, in run_until_complete
return future.result()
File ".\tmp.py", line 113, in test
print(await a(0.1))
File ".\tmp.py", line 110, in a
return await b(time)
File ".\tmp.py", line 106, in b
return await c(time)
File ".\tmp.py", line 102, in c
return await deep(time)
File ".\tmp.py", line 97, in deep
raise ValueError('some error happened')
ValueError: some error happened但只适用于第二个片段:
Traceback (most recent call last):
File ".\tmp.py", line 149, in <module>
loop.run_until_complete(test())
File ".\Python36\lib\asyncio\base_events.py", line 466, in run_until_complete
return future.result()
File ".\tmp.py", line 146, in test
print(await a(0.1))
File ".\tmp.py", line 130, in deep
raise ValueError('some error happened')
ValueError: some error happened正如您所看到的,第一次回溯帮助您看到“真实”(和有帮助的)执行流程,而第二次跟踪帮助您查看“真实”(且有帮助的)执行流程。
第一种编写代码的方法也要好得多:想象一下,一旦理解了b(time)也应该包含一些异步调用,比如await asyncio.sleep(time)。在第一个片段中,这个调用可以直接放置,而不需要进行任何其他更改,但是在第二个片段中,您必须重写代码的许多部分。
https://stackoverflow.com/questions/44223090
复制相似问题