Помогите мне, пожалуйста, разобраться в некоторых вещах asyncio.Я хочу понять, если это возможно сделать следующим образом:
У меня есть синхронная функция, которая, например, создает некоторые данные в удаленном API (API может возвращать успех или неудачу):
def sync_func(url):
... do something
return result
У меня естьсопрограмма для запуска этой операции синхронизации в executor:
async def coro_func(url)
loop = asyncio.get_event_loop()
fn = functools.partial(sync_func, url)
return await loop.run_in_executor(None, fn)
Далее я хочу сделать что-то вроде
- Если удаленный API не отвечает в течение 1 секунды, я хочу запустить следующий URLдля обработки, но я хочу знать результат первой задачи (когда API, наконец, отправит ответ), которая была прервана по таймауту.Я оборачиваю coro_func () в щит (), чтобы избежать его отмены.Но не представляю, как я могу проверить результат после ...
list_of_urls = [url1, ... urlN]
map_of_task_results = {}
async def task_processing():
for url in list_of_urls:
res = asyncio.wait_for(shield(coro_func(url), timeout=1))
if res == 'success':
return res
break
else:
map_of_task_results[url] = res
return "all tasks were processed"
PS Когда я пытаюсь получить доступ к результату щита (coro) - он имеетИсключение CancelledError ... но я ожидаю, что может быть результат, потому что я "экранировал" задачу.
try:
task = asyncio.shield(coro_func(url))
result = await asyncio.wait_for(task, timeout=API_TIMEOUT)
except TimeoutError as e:
import ipdb; ipdb.set_trace()
pending_tasks[api_details['api_url']] = task
ipdb> task
<Future cancelled created at
/usr/lib/python3.6/asyncio/base_events.py:276>
ipdb> task.exception
<built-in method exception of _asyncio.Future object at 0x7f7d41eeb588>
ipdb> task.exception()
*** concurrent.futures._base.CancelledError
`