В общем, не должно быть необходимости в специфичных для ошибки обратных вызовах.Asyncio полностью поддерживает распространение исключений через await
границы внутри сопрограмм, а также через вызовы, такие как run_until_complete
, где встречаются синхронизация и асинхронный код.Когда кто-то ожидает вашу сопрограмму, вы можете просто вызвать исключение обычным способом.
Одна ловушка связана с сопрограммами, которые выполняются как «фоновые задачи».Когда такие сопрограммы не работают, что потенциально делает библиотеку непригодной для использования, никто не будет получать уведомления автоматически.Это известный недостаток asyncio (см. здесь для подробного обсуждения), который в настоящее время решается .В то же время вы можете достичь эквивалентной функциональности с помощью кода, подобного следующему:
class Library:
async def work_forever(self):
loop = asyncio.get_event_loop()
self._exit_future = loop.create_future()
await self._exit_future
async def stop_working(self):
self._cleanup()
self._exit_future.set_result(None)
async def _failed(self):
self._cleanup()
self._exit_future.set_exception(YourExceptionType())
def _cleanup(self):
# cancel the worker tasks
...
work_forever
аналогичен serve_forever
, вызову, который может ожидать main()
сопрограммы, или даже непосредственно передано asyncio.run()
.В этом проекте библиотека может обнаружить ошибочное состояние и распространить исключение, или основная программа (предположительно через отдельно порожденную сопрограмму) может запросить ее корректный выход.