在 Python 中,当与同步调用结合使用时,awaited 语句的顺序是否重要?

4

将可以等待的操作移动到方法的顶部,以便在等待期间进行工作,这样做是否有意义?

示例

按逻辑顺序排列

async def set_new_password(user_id, new_password):
    hash = bcrypt(new_password)
    db_handle = await async_get_db_handle()
    await async_write_password(db_handle, user_id, hash)

在这里,Python会计算哈希值,然后为数据库操作创建协程,接着为写操作创建协程,最后将控制权交给事件循环以调度这两个操作。

在这种情况下,假设这是我们唯一的方法调用,我们“浪费”了时间来计算密码的哈希值,下面的方法会更快。

尽可能延迟同步

async def set_new_password(user_id, new_password):
    db_handle = await async_get_db_handle()
    hash = bcrypt(new_password)
    await async_write_password(dh_handle, user_id, hash)

在此期间等待db_handle时,密码将被哈希处理,因此我们可以利用这段“闲暇时间”做一些有用的事情。

那么我应该尽可能晚地放置不可等待语句,以便它们可以在等待语句等待时执行吗?

1个回答

5

...当等待db_handle时,密码将被散列,因此我们将利用“停机时间”做一些有用的事情。

我认为这不正确。await的效果是防止下一行代码执行,直到返回db_handle。它使调用代码像同步代码一样运行,因此正常的顺序考虑仍然适用。

如果您想在获取句柄时执行一些工作,可以使用Task

async def set_new_password(user_id, new_password):
    task = asyncio.create_task(get_db_handle())
    hash = bcrypt(new_password)
    db_handle = await task
    await async_write_password(db_handle, user_id, hash)

啊,是的。我忘记了这一点。那么事件循环只会处理其他方法中被等待的代码,而不是此方法后续的代码? - problemofficer - n.f. Monica
我认为可能并不清楚get_db_handle()也是异步的。我更改了名称以使其如此。对此我感到抱歉。 - problemofficer - n.f. Monica
是的,在被“await”阻塞时,它可以执行其他工作。(而且,我知道get_db_handle()是异步的。) - Martin Stone
文档比我讲得更好,可以参考这里 - Martin Stone
bcrypt故意变慢并且是一个阻塞调用,这不会在这种情况下打败asyncio的目的吗?所有其他协程都将被阻塞,直到bcrypt调用完成,对吗? - ant1g
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接