在Python 3.6中使用asyncio时,如果callstack中的一个函数是异步的,我是否需要使整个堆栈异步并等待每次调用?
例如我有:
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,还是需要根据异步和非异步调用更改整个调用层次结构?
-
设计这样的可以作为服务器或批处理运行的东西的最佳方法是什么?
非常感谢所有的帮助!
1 回答
答案取决于调用堆栈中的函数究竟是什么,但很可能是肯定的 .
await
effects需要异步函数与其调用者(awaiter或事件循环驱动程序)进行通信,以确保暂停/恢复其执行 .非异步函数可以在不等待的情况下参与调用堆栈,但是它只能用于传输协程对象而无法检查数据 . 例如,
func3
可以实现为:要么:
但是第一个函数可以检查(或记录等)
getData
返回的数据,而第二个函数立即退出并返回其他人必须等待的协程对象 .一旦将调用堆栈中的所有函数设置为异步,就无法传递
FileDataSource
,但这并不意味着您必须具有两个单独的调用层次结构 . 通过将def getData()
更改为async def getData()
(以及其他方式保持实现不变),只需将FileDataSource
实现为"async",并且它将用于异步使用,前提是它实际上不会阻塞 .