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

问题描述 投票:2回答:1

在文章"I'm not feeling the async pressure"中,Armin Ronacher进行了以下观察:

在线程代码中,任何函数都可以产生。在异步代码中,只有异步函数可以。例如,这意味着writer.write方法无法阻止。

此观察是参考以下代码示例进行的:

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不能阻塞的功能?
python asynchronous python-asyncio yield
1个回答
0
投票

逐行:

在线程代码中,任何函数都可以产生。

在计算机上运行的程序是根据进程来组织的。每个进程可能具有一个或多个threads。线程(如进程)由操作系统调度(并可由操作系统中断)。在此上下文中,单词“ yield”表示“让其他代码运行”。将工作分配到多个线程之间时,函数很容易“屈服”:操作系统将一个线程中运行的代码挂起,在另一个线程中运行一些代码,将其挂起,返回,然后在第一个线程上进行更多工作,等等。上。通过以这种方式在线程之间切换,可以实现并发。

在此执行模型中,被挂起的代码是同步还是异步无关紧要。线程中的代码[[inin是逐行运行的,因此不违反同步函数的基本假设-在运行一行代码和下一行代码之间不发生任何更改-。

在异步代码中,只有异步函数可以。

“异步代码”在本文中是指与多线程应用程序执行相同工作的单线程应用程序,不同之处在于它通过使用异步函数

within

线程而不是分割工作< [之间不同的线程。在此执行模型中,解释器(而不是操作系统)负责根据需要在功能之间进行切换以实现并发性。在此执行模型中,将工作挂在位于异步函数内部的同步函数中间是不安全的。这样做将意味着在运行同步功能的过程中运行其他一些代码,从而破坏了同步功能所做的“逐行”假设。结果,解释器将仅等待同步子功能之间的异步功能的执行挂起,而不会等待一个。这就是异步代码中的同步函数无法产生的语句的含义:一旦同步函数开始运行,它就必须完成。

例如,这意味着writer.write方法无法阻止。

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

严格来说,writer.write

can

块,这样做是不明智的。

如果您需要在异步函数内部进行阻塞,则正确的方法是await另一个异步函数。这就是例如await writer.drain()可以。这将异步阻止:尽管此特定功能仍然处于阻止状态,但它将正确地屈服于可以运行的其他功能。

© www.soinside.com 2019 - 2024. All rights reserved.