set_exception_handler игнорируется в python3 .6 с asyncio - PullRequest
0 голосов
/ 13 апреля 2020

Я в основном создаю объект, который должен выполнять ряд задач в асинхронном режиме c (+ другие вещи, но я попытался упростить здесь). Вот фрагмент кода для самого объекта. Это успешно (благодаря примеру Lynn Root ) в обработке сигналов - но не в обработке исключений. Или, по крайней мере, не так, как я надеюсь, что смогу справиться с ними.

class myobj(object):
    def __init__(self, loop: asyncio.AbstractEventLoop):
        self.shutdown = False
        self.loop = loop

    async def graceful_shutdown(self, s=None):
        if s is not None:
            logging.warning(f'Receiving signal {s.name}.')
        else:
            logging.warning(f'Shutting NOT via signal')
        logging.warning(f'Initiating cancellation of {len(self.tasks)} tasks...')
        [task.cancel() for task in self.tasks]
        logging.warning(f'Gaterhing out put of cancellation of {len(self.tasks)} tasks...')
        await asyncio.gather(*self.tasks, loop=self.loop, return_exceptions=True)
        logging.warning('Done graceful shutdown of subtasks')
        # Mark main task to shutdown
        self.shutdown = True

    async def run(self):
        i = 0
        taskx = self.loop.create_task(self.task_x())
        self.tasks = [taskx]
        while not self.shutdown:
            await asyncio.sleep(1)
            print(f'Main runner... {i}')
            i += 1
        logging.warning('Main runner is over.')

    async def task_x(self):
        logging.warning('Starting task X')
        i = 0
        while True:
            await asyncio.sleep(2.25)
            print(f'Doing task x... {i}')
            if i == 2:
                raise RuntimeError('BOOM X!')
            i += 1

На данный момент, из «основного» мне нужно установить несколько вещей и создать l oop:

def main():
    try:
        global newobj
        loop = asyncio.get_event_loop()
        logging.warning(f'Installing exception handler')
        loop.set_exception_handler(handle_exception)
        logging.warning(f'Creating main object')
        newobj = myobj(loop)
        logging.warning(f'Installing signal handlers')
        signals = (signal.SIGINT, signal.SIGTERM)
        for s in signals:
            loop.add_signal_handler(s, lambda s=s: loop.create_task(newobj.graceful_shutdown(s)))
        logging.warning(f'Running object...')
        loop.run_until_complete(newobj.run())
    finally:
        loop.close()
        logging.warning(f'object is Shutdown - Exiting program.')
        sys.exit(0)

if __name__ == "__main__":
    main()

Но необходимо определить handle_exception.


def handle_exception(loop, context):
    # context["message"] will always be there; but context["exception"] may not
    msg = context.get("exception", context["message"])
    logging.error(f'Caught exception: {msg}')
    logging.info(f'Shutting down from exception.')
    loop.create_task(newobj.graceful_shutdown())

Проблема в том, что он никогда не вызывает handle_exception. Мне нужно запустить это в python3 .6 по какой-то причине. Что мне здесь не хватает?

...