我最近开始用Python实现一些async
代码,并且对设计和实现有些疑问。
例如,如果我必须做一些事情,让我将同步代码称为非async
函数,而我只有一个async
函数,返回协程是否被视为不良习惯或不良设计?
让我用一些代码更好地解释一下:
def my_async_function():
#some sync code
return async_code()
代替:
async def my_async_function():
#some sync code
return await async_code()
您认为第一个版本可能会隐藏一些问题吗?
或者总的来说,每条建议都会受到赞赏,因为我是这种代码风格的新手。
附注:对不起,我的英语,我希望这是可以理解的。
答案 0 :(得分:0)
两个变体都是完全正确的,但是如果有疑问,请选择第二个变体。这将使呼叫者清楚地知道他们正在处理协程,并且仅与协程进行处理。
两者之间存在技术上的区别,但是只有在呼叫者不立即等待时,它才会变得明显。考虑以下代码:
aw = my_async_function()
# ... do something here ...
result = await aw
在您的第一个示例中,“某些同步代码”将在您调用该函数后立即运行,因此,如果有副作用,则可以在“在此处执行操作”中看到它们。在第二个示例中,仅调用my_async_function()
是完全没有副作用的,它仅创建协程对象。在该变体中,“某些同步代码”仅在await aw
上执行,即在“在这里做某事”已经运行之后。
将协程定义为async def
可确保调用方在实际等待协程结果之前不会运行任何同步代码,这可能是重要的保证。即使该函数不是async
且仅返回一个等待的值,也应建议其行为好像坚持这一保证,至少在调用者可以观察到的范围内。< / p>
一个不遵循该原理的著名示例是run_in_executor
,它立即将可调用对象提交到线程池。因此,run_in_executor
永远无法成为真正的协程,因为这样会破坏调用它的代码,而不会打扰await
(或由于任何原因而等待的代码)。