【问题标题】:async def and call stack异步 def 和调用堆栈
【发布时间】:2018-07-03 14:21:12
【问题描述】:

在 Python 3.6 中使用 asyncio 时,如果调用堆栈深处的一个函数是异步的,我是否需要使整个堆栈异步并在每次调用时都等待?
例如我有:

class FileDataSource:  
    def getData(self):  
        return pd.read_csv('/some/file')

class SocketDataSource:
    def __init__(self, host, port):
        self.reader, self.writer = yield from asyncio.open_connection(host, port)

    async def getData(self):
        data = await self.reader.readuntil(b'\n\n')
        return data

def func1(datasource):
    func2(datasource)

def func2(datasource):
    func3(datasource)

def func3(datasource):
    datasource.getData()

def main(host, port):
    if host is None:
        func1(FileDataSource())
    else:
        loop = asyncio.get_event_loop()
        for timeout in range(1, 60):
            loop.call_later(timeout, func1(SocketDataSource(host, port)))
        loop.run_forever()
  1. 在上面的示例中,我是否需要将 func1 / 2 / 3 的整个调用堆栈设置为异步并等待所有它们? (恐怕答案是肯定的)

  2. 我可以将 FileDataSource 和 SocketDataSource 交替传递给 func1,还是需要根据异步调用和非异步调用更改整个调用层次结构?

  3. 设计这样一个可以作为服务器或批处理运行的东西的最佳方法是什么?

非常感谢您的所有帮助!

【问题讨论】:

  • 您是否尝试过运行代码并出现错误?
  • 是的 - 当我使 func[123] 异步并等待所有这些时它运行。我很好奇是否有办法不这样做 - 即无论是读取文件还是套接字,都使 getData() 接口相同。
  • 我现在正在度假,但打算回到办公室尝试一下。我将发表评论以结束该主题。谢谢你的帮助!!

标签: python python-3.x python-asyncio


【解决方案1】:

如果调用堆栈深处的一个函数是异步的,我是否需要使整个堆栈异步并在每次调用时都等待?

答案取决于调用堆栈中的函数究竟做了什么,但很可能是的。 await effects 要求 async 函数与其调用者(等待者或事件循环驱动程序)通信,以确保暂停/恢复其执行。

一个非异步函数可以不等待就参与调用栈,但是它只能用于传输协程对象,不能检查数据。例如,func3 可以实现为:

async def func3(datasource):
    return await datasource.getData()

或:

def func3(datasource):
    return datasource.getData()

但第一个函数可以检查(或记录等)getData 返回的数据,而第二个函数立即退出并返回其他人必须等待的协程对象。

我可以将FileDataSourceSocketDataSource 交替传递给func1,还是我需要根据异步调用和非异步调用更改整个调用层次结构?

一旦将调用堆栈中的所有函数设为异步,您将无法传递FileDataSource,但这并不意味着您必须拥有两个单独的调用层次结构。只需将def getData() 更改为async def getData()(否则保持实现不变),将FileDataSource 实现为简单的“异步”,只要它实际上没有阻塞,它将适用于异步使用。

【讨论】:

  • 感谢您的详细回复。我意识到使 func[123] 异步有效。然而,整个想法是隐藏数据的接收方式,getData 应该返回实际数据,无论它来自文件还是套接字。我想知道是否有办法让“等待”实际等待结果并在套接字读取完成时恢复执行。
  • @DGandhi 整个想法是隐藏数据的接收方式,getData 应该返回实际数据,无论它来自文件还是套接字 - 你可以轻松做到这一点,只需使getData async 并在文件情况下立即从它返回,在套接字情况下从适当的流中等待。
  • @DGandhi 我想知道是否有办法让 'await' 实际上等待结果并在套接字读取完成时恢复执行 当然,这正是它的用途!异步getData 可以等待asyncio.open_connection 来获取一对流。它可以通过等待流的read方法(或readline等)来获取数据。
猜你喜欢
  • 2016-05-25
  • 2019-08-03
  • 2013-03-31
  • 2021-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多