Перед созвонами с клиентами я запускаю небольшой скрипт, который оценивает сайт каждого клиента по трём метрикам, с весами для каждого клиента, которые подтягиваются с их analytics endpoint. Запросы идут через asyncio.gather с return_exceptions=True, чтобы один сломанный клиент не отменял остальных, верно? fetch_weights бросает ValueError, когда ответ пустой, и я обернул gather в try/except ValueError, чтобы залогировать warning и откатиться на веса по умолчанию.
Первый клиент выводит оценку, потом скрипт падает на eastside-cycles, у которого пустой ответ. Сообщения "falling back to defaults" нет вообще. Я поменял на except Exception, а ещё запускал с python3 -X dev main.py, и ничего не изменилось.
Не понимаю вот что: в TypeError упоминается объект ValueError, хотя ValueError явно бросается в fetch_weights.
juniper-florals: 83.0
Traceback (most recent call last):
File "main.py", line 59, in <module>
main()
File "main.py", line 55, in main
asyncio.run(score_all(clients))
...
File "main.py", line 40, in score_all
value = score(client["metrics"], weights)
File "main.py", line 26, in score
return round(sum(metrics[k] * weights[k] for k in weights), 1)
TypeError: 'ValueError' object is not iterable
Нужная часть main.py:
async def score_all(clients):
try:
all_weights = await asyncio.gather(
*(fetch_weights(c) for c in clients),
return_exceptions=True,
)
except ValueError:
log.warning("weights fetch failed, falling back to defaults")
all_weights = [DEFAULT_WEIGHTS for _ in clients]
for client, weights in zip(clients, all_weights):
value = score(client["metrics"], weights)
print(client["slug"] + ": " + str(value))
Почему обработчик пропускается?