在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()
在上面的示例中,我是否需要将func1 / 2/3的整个调用堆栈设为异步并等待所有这些调用? (恐怕答案是肯定的)
我可以互换地将FileDataSource和SocketDataSource传递给func1还是我需要基于异步与非异步调用更改整个调用层次结构?
设计可以作为服务器或批处理运行的类似内容的最佳方法是什么?
非常感谢所有帮助!
答案 0 :(得分:3)
如果调用堆栈中的一个函数是异步的,我是否需要使整个堆栈异步并在每次调用时都处于等待状态?
答案取决于调用堆栈中函数的确切功能,但很可能是。 await
的影响要求异步功能与其调用方(即等待方或事件循环驱动程序)进行通信,以确保中止/恢复执行。
非异步功能可以不等待而参与调用堆栈,但是它只能用于传输协程对象,并且不能检查数据。例如,func3
可以实现为:
async def func3(datasource):
return await datasource.getData()
或:
def func3(datasource):
return datasource.getData()
但是第一个函数可以检查(或记录等)getData
返回的数据,而第二个函数立即退出并返回其他人必须等待的协程对象。
我可以互换地将
FileDataSource
和SocketDataSource
传递给func1
还是需要基于异步与非异步呼叫来更改整个呼叫层次结构?
一旦使调用栈中的所有功能异步,您将无法传递FileDataSource
,但这并不意味着您必须具有两个单独的调用层次结构。只需将FileDataSource
更改为def getData()
即可将async def getData()
实现为“异步”(否则将实现保持不变),并且只要不实际阻塞,它将适用于异步使用。