5

У меня есть две проблемы с concurrent.futures:От concurrent.futures к asyncio

Как сломать time.sleep() в питоне concurrent.futures?

Вывод: time.sleep() не может быть прерван. Одно из решений: вы можете написать цикл вокруг него и сделать короткие спячки.

How to break time.sleep() in a python concurrent.futures См

Индивидуальные таймаутов для concurrent.futures?

Заключение: индивидуальные тайм-ауты должны выполняться пользователем. Например: для каждого таймаута вы можете позвонить по номеру wait().

См Individual timeouts for concurrent.futures

Вопрос

ли решить asyncio диссертаций проблемы?

+0

Ради самоограничения, можете ли вы обобщить эти два других вопроса здесь? – deceze

+0

@deceze, я обновил вопрос и добавил свой вывод. Это нормально, или еще что-то не хватает? – guettli

+0

Выглядит теперь более ответственно, спасибо. – deceze

ответ

5

В модели Asyncio выполнение запланировано и координируется контуром события. Чтобы отменить выполнение приостановленной задачи, вам по существу просто нужно не возобновить. Хотя на практике это немного отличается от практики, должно быть очевидно, что это упрощает теоретическую отмену приостановленной задачи.

Индивидуальные тайм-ауты, безусловно, возможны одинаково: всякий раз, когда вы приостанавливаете сопрограмму для ожидания результата, вы хотите указать значение тайм-аута. Цикл событий будет обеспечивать отмену ожидающей задачи, когда этот тайм-аут будет достигнут, а задача еще не завершена.

Некоторые образцы бетона:

>>> import asyncio 
>>> loop = asyncio.get_event_loop() 
>>> task = asyncio.ensure_future(asyncio.sleep(5)) 
>>> task.cancel() 
>>> loop.run_until_complete(task) 
Traceback (most recent call last): 
    ... 
concurrent.futures._base.CancelledError 

На практике это может быть реализовано с помощью что-то вроде этого:

class Foo: 
    task = None 

    async def sleeper(self): 
     self.task = asyncio.sleep(60) 
     try: 
      await self.task 
     except concurrent.futures.CancelledError: 
      raise NotImplementedError 

Хотя этот метод спит, кто-то может назвать foo.task.cancel() разбудить сопрограмму и пусть он справится с отменой. В качестве альтернативы, тот, кто звонит sleeper(), может отменить его напрямую, не давая ему возможности почистить.

Настройка времени ожидания аналогично легко:

>>> loop.run_until_complete(asyncio.wait_for(asyncio.sleep(60), 5)) 
[ ... 5 seconds later ... ] 
Traceback (most recent call last): 
    ... 
concurrent.futures._base.TimeoutError 

В частности, в контексте HTTP таймаутов запроса см aiohttp:

async def fetch_page(session, url): 
    with aiohttp.Timeout(10): 
     async with session.get(url) as response: 
      assert response.status == 200 
      return await response.read() 

with aiohttp.ClientSession(loop=loop) as session: 
    content = loop.run_until_complete(fetch_page(session, 'http://python.org')) 

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

+0

Ничего себе, отличный ответ. Спасибо. Представьте, что я использую модуль подпроцесса (я читал, что он поддерживается), тогда я хочу как-то прекратить подпроцесс. У вас есть подсказка, как это сделать? – guettli

+0

Не совсем, нет.Вы должны открыть для этого новый вопрос. – deceze

+2

@guettli Просмотрите модуль [asyncio.subprocess] (https://docs.python.org/3/library/asyncio-subprocess.html) и те [примеры] (http://asyncio.readthedocs.io /en/latest/subprocess.html). – Vincent

Смежные вопросы