если одна функция глубоко в стеке вызовов является асинхронной, нужно ли делать весь стек асинхронным и ставить await при каждом вызове?
Ответ зависит от того, что именно выполняют функции в стеке вызовов, но, скорее всего, да. 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()
(и в противном случае оставив реализацию без изменений), и она будет работать для асинхронного использования, при условии, что она фактически не блокируется.