我最近开始用 Python 实现一些异步
代码,我对设计和实现有一些疑问。
例如,如果我必须做一些事情,让我将同步代码作为非async
函数调用,并且我只有一个async
函数,返回协程被认为是坏习惯还是坏设计?
让我用一些代码更好地解释一下:
def my_async_function():
#some sync code
return async_code()
而不是:
async def my_async_function():
#some sync code
return await async_code()
您认为第一个版本可能隐藏一些问题吗?
或者总的来说,每一条建议都会受到赞赏,因为我对这种风格的代码很陌生。
P.S.:抱歉我的英语不好,我希望它是可以理解的。
最佳答案
两种变体都是完全正确的,但如果有疑问,请选择第二个。它将使调用者清楚地知道他们正在处理一个协程,并且只是一个协程。
两者之间存在技术差异,但只有当调用者不立即等待时,这种差异才会变得明显。考虑以下代码:
aw = my_async_function()
# ... do something here ...
result = await aw
在您的第一个示例中,“某些同步代码”将在您调用该函数后立即运行,因此如果它有副作用,它们将在“在此处执行某些操作”中可见。在第二个示例中,仅调用 my_async_function() 是完全无副作用的,它仅创建协程对象。在该变体中,“某些同步代码”仅在 await aw
时执行,即“在此处执行某些操作”已经运行之后。
将协程定义为 async def
可以向调用者保证,在实际等待协程结果之前不会运行任何同步代码,这可能是一个重要的保证。即使该函数不是异步
并且仅返回一个可等待的,也最好表现得就像它支持这种保证,至少在调用者可以观察到的范围内它。
一个不遵守此原则的著名示例是 run_in_executor
它立即将可调用对象提交到线程池。因此,run_in_executor
永远不能成为一个实际的协程,因为这会破坏调用它而不费心 await
的代码(或者出于某种原因只在稍后等待的代码) .
关于python - 异步设计/实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56038047/