Имею ли я дело с асинхронной задачей, игнорирующей правильно CancelledError? - PullRequest
0 голосов
/ 14 февраля 2019

Я не спрашиваю, как отменить такую ​​задачу.Это невозможно, и это объясняется здесь: https://stackoverflow.com/a/33578893/5378816

Меня беспокоит это изменение в wait_for :

Изменено в версии 3.7: Когдаотменен из-за тайм-аута, wait_for ожидает отмены w.Ранее он сразу вызывал asyncio.TimeoutError.

Не поймите меня неправильно, мне это нравится, это улучшение.

Однако эта программа теперь зависает wait_for (Python 3.7):

import asyncio

async def uncancellable():
    while True:
        try:
            await asyncio.sleep(99)
        except asyncio.CancelledError:
            print("sorry!")

TIMEOUT = 1.0

async def test():
    task = asyncio.get_event_loop().create_task(uncancellable())
    try:
        await asyncio.wait_for(task, TIMEOUT)
    except asyncio.TimeoutError:
        print("timeout")

asyncio.get_event_loop().run_until_complete(test())

Невозможная задача - ошибка программирования.Но если мне нужно быть оборонительным , как я могу предотвратить бесконечное зависание wait_for?

Я попробовал это.Первый тайм-аут: до отмены, второй тайм-аут: до отказаКогда он поднимается asyncio.TimeoutError Я не могу сказать, произошло ли это в первый или во второй тайм-аут.В основном я думаю, что это работает, но действительно ли это правильно?

1 Ответ

0 голосов
/ 15 февраля 2019

Но если мне нужно быть в обороне, как я могу предотвратить бесконечное зависание wait_for?

Я не думаю, что каждая задача потенциально невыполнима - хорошая идея.

Обычно вы просто предполагаете, что такой ситуации не произойдет, и это нормально, потому что, да, невыполнимая задача - это ошибка программирования, и это не та ошибка, которую вы ожидаете увидеть часто.Точно так же, как вы обычно не ожидаете, что какой-то внутренний код будет подавлять KeyboardInterrupt или любой другой BaseException.

Нет ничего плохого в том, что сторонний код будет следовать некоторым контрактам (например,в приведенном выше примере или, скажем, не случайно позвонить sys.exit()).В противном случае вам придется написать много больше кода и, вероятно, все еще не охватить все возможные случаи.

...