<p>aiohttp не должен вызывать обработчик исключений в неисключительных ситуациях.</p>

Созданный на 10 нояб. 2020  ·  4Комментарии  ·  Источник: aio-libs/aiohttp

🐞 Опишите ошибку
Когда происходит утечка определенных объектов из aiohttp, они вызывают обработчик исключений asyncio, что в некоторых средах (например, при использовании aiorun с stop_on_unhandled_errors=True ) означает, что вся программа останавливается.

Например, вот соответствующий код в ClientResponse :

https://github.com/aio-libs/aiohttp/blob/a8d9ec3f1667463e80545b1cacc7833d1ff305e9/aiohttp/client_reqrep.py#L748 -L751

💡 Воспроизвести
Утечка объекта aiohttp, который это делает.

💡 Ожидаемое поведение
Утечка объектов не должна вызывать исключения по той же причине, что open() ing файл, а не .close() ing, не вызывает исключения.

Все объекты, которые делают это, похоже, уже вызывают предупреждение об утечке ресурсов - я не вижу причин для них также вызывать обработчик исключений.

📋 Ваша версия Python

$ python --version
Python 3.8.6

📋 Ваша версия дистрибутивов aiohttp / yarl / multidict

$ python -m pip show aiohttp
Name: aiohttp
Version: 3.6.2

консоль
$ python -m pip show multidict
Имя: multidict
Версия: 4.7.6

```console
$ python -m pip show yarl
Name: yarl
Version: 1.5.1

📋 Дополнительный контекст
cjrh / aiorun # 56

bug wontfix

Все 4 Комментарий

Я не согласен.
Незакрытый ресурс - это достаточно серьезная ошибка программирования, которую легко исправить, написав правильный код.
Например, сам asyncio использует call_exception_handler() для сообщения о непредвиденных асинхронных вызовах.
Если вы не хотите писать педантичный код - можете использовать stop_on_unhandled_errors=False .

Так почему бы тогда не вызвать настоящее исключение?

Я предполагаю, потому что создание исключения в __del__ будет проигнорировано. Но так и должно быть, не так ли? Очень сложно отладить «что-то выделяет объект и не закрывает его должным образом», особенно когда ошибка не в вашем собственном коде, а в какой-то библиотеке; контекстный ключ source_traceback недокументирован, и кажется недружелюбным полагаться на недокументированное поведение обработчика исключений asyncio по умолчанию, чтобы сделать возможным отладку утечек памяти.

Я также не вижу, где asyncio использует call_exception_handler() для предупреждения о непредвиденных сопрограммах. Когда неожиданная сопрограмма собирает мусор, она вызывает _PyErr_WarnUnawaitedCoroutine :

    /* If `gen` is a coroutine, and if it was never awaited on,
       issue a RuntimeWarning. */
    if (gen->gi_code != NULL &&
        ((PyCodeObject *)gen->gi_code)->co_flags & CO_COROUTINE &&
        gen->gi_frame->f_lasti == -1)
    {
        _PyErr_WarnUnawaitedCoroutine((PyObject *)gen);
    }

который вызывает warnings._warn_unawaited_coroutine() :

void
_PyErr_WarnUnawaitedCoroutine(PyObject *coro)
{
    /* First, we attempt to funnel the warning through
       warnings._warn_unawaited_coroutine.

который испускает RuntimeWarning. Я не вижу, чтобы call_exception_handler() где-либо использовалось - на самом деле я не вижу никакого использования call_exception_handler() в stdlib, которое не включает exception в контексте.

И снова: если забывание закрыть файл не вызывает исключения, почему следует забывать очищать любой случайный объект aiohttp?

Вы правы, создание исключения из метода __del__ - обескураживающая практика.
Вот почему нам нужно другое сигнальное решение.
Asyncio делает вызов call_exception_handler() от __del__ см Task.__del__ , например: https://github.com/python/cpython/blob/master/Lib/asyncio/tasks.py # L139 -L148

Вы правы, source_traceback не задокументировано в https://docs.python.org/3/library/asyncio-eventloop.html?highlight=call_exception_handler#asyncio.loop.call_exception_handler
Не могли бы вы создать запрос на перенос на

И снова: если забывание закрыть файл не вызывает исключения, почему следует забывать очищать любой случайный объект aiohttp?

aiohttp не вызывает исключение из __del__ тоже, это просто невозможно в Python , потому что вызов объекта финализации является индетерминисти-.

Незакрытый файл вызывает ResourceWarning . По умолчанию это предупреждение игнорируется: https://docs.python.org/3/library/warnings.html#default -warning-filter
Вот почему такого рода предупреждения не видны очень многим разработчикам, если они не включили их явно. Это сделано частично по историческим причинам: долгое время такого рода предупреждения не существовало, многие библиотеки не вызывают file.close() потому что их авторы не знают о необходимости изящной очистки ресурсов и т. Д. И т. Д. .

К счастью, file.close() можно безопасно вызвать из file.__del__ , это обычный вызов.
Но в мире asyncio close() очень часто отличается: это должна быть асинхронная функция, которую нельзя вызвать из __del__ .
Например, transport.close() без ожидания protocol.connection_lost() приводит к предупреждению даже для простых сокетов; для SSL ситуация еще хуже.
aiohttp немного беспорядок с синхронизаторами / асинхронными финализаторами, но я над этим работаю; aiohttp 4.0 следует значительно почистить.

Вот почему очистка очень важна, должно быть выдано предупреждение, и call_exception_handler() будет использоваться, чтобы сделать неправильное использование более заметным.

Asyncio _does_ вызывает call_exception_handler() из __del__ , например, см. Task.__del__

Честно говоря, я пропустил этот звонок.

Не могли бы вы создать запрос на перенос на python / cpython, чтобы исправить документацию?

Честно говоря, я не уверен, как лучше всего это задокументировать. Я создал bpo-42347, так как заметил некоторые другие несоответствия между документами,

Вот почему очистка очень важна, должно быть выдано предупреждение, а call_exception_handler () будет использоваться, чтобы сделать неправильное использование более заметным.

Я думаю, это просто неприятно, когда вы получаете ошибки, потому что библиотека, которую вы используете, не очищает себя должным образом. Я не понимал, что это настолько важно, что должно остановить приложение, и поначалу даже не понимал, что утечка была причиной того, что aiorun останавливал цикл.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

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

yuval-lb picture yuval-lb  ·  5Комментарии

thehesiod picture thehesiod  ·  4Комментарии

asvetlov picture asvetlov  ·  4Комментарии

zhmiao picture zhmiao  ·  3Комментарии

ZeusFSX picture ZeusFSX  ·  5Комментарии