Example #1
0
def _shutdown_tasks(loop: asyncio.AbstractEventLoop) -> None:
    """Завершение в случае ошибки.

    После ошибки происходит отмена всех заданий, чтобы не захламлять сообщение об ошибке множеством
    сообщений, о том, что результат выполнения задания не был awaited.

    Идея кода позаимствована из реализации asyncio.app.
    """
    to_cancel = asyncio.all_tasks(loop)
    if not to_cancel:
        return

    for task in to_cancel:
        task.cancel()

    loop.run_until_complete(asyncio.gather(*to_cancel, loop=loop, return_exceptions=True))

    for canceled_task in to_cancel:
        if canceled_task.cancelled():
            continue
        if canceled_task.exception() is not None:
            loop.call_exception_handler(
                {
                    "message": "unhandled EventBus exception",
                    "exception": canceled_task.exception(),
                    "task": canceled_task,
                },
            )

    loop.run_until_complete(loop.shutdown_asyncgens())
    loop.run_until_complete(loop.shutdown_default_executor())
Example #2
0
File: bot.py Project: Reliku/hikari
    def _destroy_loop(loop: asyncio.AbstractEventLoop) -> None:
        async def murder(future: asyncio.Future[typing.Any]) -> None:
            # These include _GatheringFuture which must be awaited if the children
            # throw an asyncio.CancelledError, otherwise it will spam logs with warnings
            # about exceptions not being retrieved before GC.
            try:
                _LOGGER.log(ux.TRACE, "killing %s", future)
                future.cancel()
                await future
            except asyncio.CancelledError:
                pass
            except Exception as ex:
                loop.call_exception_handler({
                    "message":
                    "Future raised unexpected exception after requesting cancellation",
                    "exception": ex,
                    "future": future,
                })

        remaining_tasks = [
            t for t in asyncio.all_tasks(loop)
            if not t.cancelled() and not t.done()
        ]

        if remaining_tasks:
            _LOGGER.debug("terminating %s remaining tasks forcefully",
                          len(remaining_tasks))
            loop.run_until_complete(
                asyncio.gather(*(murder(task) for task in remaining_tasks)))
        else:
            _LOGGER.debug("No remaining tasks exist, good job!")

        if sys.version_info >= (3, 9):
            _LOGGER.debug("shutting down default executor")
            with contextlib.suppress(NotImplementedError):
                # This seems to raise a NotImplementedError when running with uvloop.
                loop.run_until_complete(loop.shutdown_default_executor())

        _LOGGER.debug("shutting down asyncgens")
        loop.run_until_complete(loop.shutdown_asyncgens())

        _LOGGER.debug("closing event loop")
        loop.close()