В логе было «не удалось получить данные:» и дальше пустота. Это и была вся ошибка

habrahabr.ru · world
Full story

A developer’s data collector logged the line “failed to get data:” with nothing after it for years. They initially assumed it was a formatting bug, but found the code was correct because asyncio.TimeoutError has an empty str(). A nearby helper retries three times with a five-second pause and was written for network failures, but it catches aiohttp.ClientError. The source cuts off while mentioning a change starting with Python 3.11 involving asyncio.

В логе моего сборщика данных годами появлялась строка «не удалось получить данные:» и дальше ничего. Я считал это багом форматирования, пока не посмотрел: код написан правильно, просто у asyncio.TimeoutError пустой str() . Дальше выяснилось интереснее. Рядом лежит хелпер с тремя попытками и паузой в пять секунд, написанный ровно под сетевые сбои, а ловит он except aiohttp.ClientError . Начиная с Python 3.11 asyncio.TimeoutError это встроенный TimeoutError , наследник OSError , и к иерархии aiohttp он отношения не имеет. То есть единственная ошибка, ради которой ретраи существовали, пролетала мимо них. Причём у aiohttp есть и свои таймаутные исключения, которые как раз ClientError , и именно это сбивает с толку. Заодно разбираю, как я на основе этих пустых ошибок записал в заметки несуществующее «сетевое ограничение VPS» и построил вокруг него архитектурное решение. Читать далее

Read full article → Compare