python - 为什么只有异步函数才能在异步代码中产生?

标签 python asynchronous python-asyncio yield

文章中"I'm not feeling the async pressure" Armin Ronacher 做出以下观察:

In threaded code any function can yield. In async code only async functions can. This means for instance that the writer.write method cannot block.

此观察是引用以下代码示例得出的:

from asyncio import start_server, run

async def on_client_connected(reader, writer):
    while True:
        data = await reader.readline()
        if not data:
            break
        writer.write(data)

async def server():
    srv = await start_server(on_client_connected, '127.0.0.1', 8888)
    async with srv:
        await srv.serve_forever()

run(server())

我不明白这个评论。具体来说:

  • 为什么同步函数在异步函数内部时无法yield
  • yield 与阻塞执行有什么关系?为什么一个函数不能yield,就不能阻塞?

最佳答案

逐行进行:

In threaded code any function can yield.

机器上运行的程序是按照进程来组织的。每个进程可能有一个或多个线程。线程与进程一样,由操作系统调度(并且可中断)。在这种情况下,“yield”一词的意思是“让其他代码运行”。当工作在多个线程之间分割时,函数很容易“屈服”:操作系统挂起在一个线程中运行的代码,在另一个线程中运行一些代码,挂起该代码,返回,然后在第一个线程上再工作一些,等等在。通过这种方式在线程之间切换,就实现了并发。

在此执行模型中,被挂起的代码是同步还是异步并不重要。线程内的代码是逐行运行的,因此同步函数的基本假设——运行一行代码与下一行代码之间没有发生任何变化——是没有违反。

In async code only async functions can.

在此上下文中,“异步代码”是指单线程应用程序,它与多线程应用程序执行相同的工作,不同之处在于它通过使用线程内的异步函数来实现并发,而不是使用线程内的异步函数。在不同线程之间分配工作。在此执行模型中,您的解释器(而不是操作系统)负责根据需要在函数之间进行切换以实现并发。

在此执行模型中,在位于异步函数内部的同步函数中间挂起工作是不安全的。这样做意味着在运行同步函数的过程中运行一些其他代码,从而打破了同步函数所做的“逐行”假设。

因此,解释器只会在同步子函数之间等待暂停异步函数的执行,而不会在同步子函数内等待。这就是异步代码中的同步函数不能产生的意思:一旦同步函数开始运行,它就必须完成。

This means for instance that the writer.write method cannot block.

writer.write 方法是同步的,因此在异步程序中运行时是不间断的。如果此方法被阻塞,它不仅会阻塞其内部运行的异步函数,还会阻塞整个程序。那会很糟糕。 writer.write 通过写入写入缓冲区并立即返回来避免阻塞程序。

严格来说,writer.write可以阻塞,但不建议这样做。

如果您需要在异步函数内部阻塞,正确的方法是等待另一个异步函数。这就是例如await writer.drain() 会这样做。这将异步阻塞:虽然此特定函数保持阻塞状态,但它将正确让步给可以运行的其他函数。

关于python - 为什么只有异步函数才能在异步代码中产生?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59557125/

相关文章:

javascript - 如果两个 promise 同时解决,这是否可能是竞争条件?

python - 如何使用 hypercorn.asyncio.serve(app,quart_cfg) 打开 Debug模式

python - asyncio - 不止一次等待协程(周期性任务)

python - 如何使用 Python OpenCV 确定内部轮廓和外部轮廓?

python - 2 groupby 在同一个数据框中,可能吗?

iphone - 我们有什么理由不使用 UIImageView 的子类吗?

javascript - Promise + async.js

python-3.x - Python 跨不同类的 asyncio.Event()

python - scipy.optimize 中的线性约束

python - 我什么时候真正使用类