> **Источник:** https://python-all.ru/3.9/library/devmode.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# Режим разработки Python

Добавлено в версии 3.7.

Режим разработки Python добавляет дополнительные проверки во время выполнения, которые слишком ресурсоёмки, чтобы быть включёнными по умолчанию. Если код корректен, он не должен выводить больше сообщений, чем обычно; новые предупреждения появляются только при обнаружении проблемы.

Его можно включить с помощью опции командной строки [`-X dev`](https://python-all.ru/3.9/using/cmdline.html#id5) или установив переменную окружения [`PYTHONDEVMODE`](https://python-all.ru/3.9/using/cmdline.html#envvar-PYTHONDEVMODE) в значение `1`.

# Эффекты режима разработки Python

Включение режима разработки Python аналогично следующей команде, но с дополнительными эффектами, описанными ниже:

```python
PYTHONMALLOC=debug PYTHONASYNCIODEBUG=1 python3 -W default -X faulthandler
```

Эффекты режима разработки Python:

- Добавляет `default` [фильтр предупреждений](https://python-all.ru/3.9/library/warnings.html#describing-warning-filters). Отображаются следующие предупреждения:

  - [`DeprecationWarning`](https://python-all.ru/3.9/library/exceptions.html#DeprecationWarning)
  - [`ImportWarning`](https://python-all.ru/3.9/library/exceptions.html#ImportWarning)
  - [`PendingDeprecationWarning`](https://python-all.ru/3.9/library/exceptions.html#PendingDeprecationWarning)
  - [`ResourceWarning`](https://python-all.ru/3.9/library/exceptions.html#ResourceWarning)

  Обычно указанные выше предупреждения отфильтровываются стандартными [фильтрами предупреждений](https://python-all.ru/3.9/library/warnings.html#describing-warning-filters).

  Поведение аналогично использованию опции командной строки [`-W default`](https://python-all.ru/3.9/using/cmdline.html#cmdoption-w).

  Используйте опцию командной строки [`-W error`](https://python-all.ru/3.9/using/cmdline.html#cmdoption-w) или установите переменную окружения [`PYTHONWARNINGS`](https://python-all.ru/3.9/using/cmdline.html#envvar-PYTHONWARNINGS) в значение `error`, чтобы обрабатывать предупреждения как ошибки.
- Устанавливает отладочные перехватчики на распределители памяти для проверки:

  - Опустошение буфера (buffer underflow)
  - Переполнение буфера
  - Нарушение API распределителя памяти
  - Небезопасное использование GIL

  См. функцию [`PyMem_SetupDebugHooks()`](https://python-all.ru/3.9/c-api/memory.html#c.PyMem_SetupDebugHooks) на языке C.

  Поведение аналогично установке переменной окружения [`PYTHONMALLOC`](https://python-all.ru/3.9/using/cmdline.html#envvar-PYTHONMALLOC) в значение `debug`.

  Чтобы включить режим разработки Python без установки отладочных перехватчиков на распределители памяти, установите переменную окружения [`PYTHONMALLOC`](https://python-all.ru/3.9/using/cmdline.html#envvar-PYTHONMALLOC) в значение `default`.
- Вызовите [`faulthandler.enable()`](https://python-all.ru/3.9/library/faulthandler.html#faulthandler.enable) при запуске Python, чтобы установить обработчики для `SIGSEGV`, `SIGFPE`, `SIGABRT`, `SIGBUS` и `SIGILL` сигналов и вывести трассировку Python при аварийном завершении.

  Поведение аналогично использованию опции командной строки [`-X faulthandler`](https://python-all.ru/3.9/using/cmdline.html#id5) или установке переменной окружения [`PYTHONFAULTHANDLER`](https://python-all.ru/3.9/using/cmdline.html#envvar-PYTHONFAULTHANDLER) в значение `1`.
- Включает [отладочный режим asyncio](https://python-all.ru/3.9/library/asyncio-dev.html#asyncio-debug-mode). Например, [`asyncio`](https://python-all.ru/3.9/library/asyncio.html#module-asyncio) проверяет корутины, которые не были ожиданы (awaited), и регистрирует их.

  Поведение аналогично установке переменной окружения [`PYTHONASYNCIODEBUG`](https://python-all.ru/3.9/using/cmdline.html#envvar-PYTHONASYNCIODEBUG) в значение `1`.
- Проверяет аргументы *encoding* и *errors* для операций кодирования и декодирования строк. Примеры: [`open()`](https://python-all.ru/3.9/library/functions.html#open), [`str.encode()`](https://python-all.ru/3.9/library/stdtypes.html#str.encode) и [`bytes.decode()`](https://python-all.ru/3.9/library/stdtypes.html#bytes.decode).

  По умолчанию для максимальной производительности аргумент *errors* проверяется только при первой ошибке кодирования/декодирования, а аргумент *encoding* иногда игнорируется для пустых строк.
- Деструктор [`io.IOBase`](https://python-all.ru/3.9/library/io.html#io.IOBase) регистрирует исключения `close()`.
- Устанавливает атрибут `dev_mode` объекта [`sys.flags`](https://python-all.ru/3.9/library/sys.html#sys.flags) в значение `True`.

Режим разработки Python не включает модуль [`tracemalloc`](https://python-all.ru/3.9/library/tracemalloc.html#module-tracemalloc) по умолчанию, поскольку накладные расходы (на производительность и память) были бы слишком велики. Включение модуля [`tracemalloc`](https://python-all.ru/3.9/library/tracemalloc.html#module-tracemalloc) предоставляет дополнительную информацию о происхождении некоторых ошибок. Например, [`ResourceWarning`](https://python-all.ru/3.9/library/exceptions.html#ResourceWarning) регистрирует трассировку, где был выделен ресурс, а ошибка переполнения буфера регистрирует трассировку, где был выделен блок памяти.

Режим разработки Python не препятствует тому, чтобы опция командной строки [`-O`](https://python-all.ru/3.9/using/cmdline.html#cmdoption-o) удаляла операторы [`assert`](https://python-all.ru/3.9/reference/simple_stmts.html#assert) или устанавливала [`__debug__`](https://python-all.ru/3.9/library/constants.html#__debug__) в значение `False`.

Изменено в версии 3.8: Деструктор [`io.IOBase`](https://python-all.ru/3.9/library/io.html#io.IOBase) теперь регистрирует исключения `close()`.

Изменено в версии 3.9: Аргументы *encoding* и *errors* теперь проверяются для операций кодирования и декодирования строк.

# Пример ResourceWarning

Пример сценария, подсчитывающего количество строк текстового файла, указанного в командной строке:

```python
import sys

def main():
    fp = open(sys.argv[1])
    nlines = len(fp.readlines())
    print(nlines)
    # Файл закрывается неявно

if __name__ == "__main__":
    main()
```

Сценарий не закрывает файл явно. По умолчанию Python не выводит никаких предупреждений. Пример с файлом README.txt, который содержит 269 строк:

```console
$ python3 script.py README.txt
269
```

Включение режима разработки Python отображает предупреждение [`ResourceWarning`](https://python-all.ru/3.9/library/exceptions.html#ResourceWarning):

```console
$ python3 -X dev script.py README.txt
269
script.py:10: ResourceWarning: unclosed file <_io.TextIOWrapper name='README.rst' mode='r' encoding='UTF-8'>
  main()
ResourceWarning: Enable tracemalloc to get the object allocation traceback
```

Кроме того, включение [`tracemalloc`](https://python-all.ru/3.9/library/tracemalloc.html#module-tracemalloc) показывает строку, в которой файл был открыт:

```console
$ python3 -X dev -X tracemalloc=5 script.py README.rst
269
script.py:10: ResourceWarning: unclosed file <_io.TextIOWrapper name='README.rst' mode='r' encoding='UTF-8'>
  main()
Object allocated at (most recent call last):
  File "script.py", lineno 10
    main()
  File "script.py", lineno 4
    fp = open(sys.argv[1])
```

Исправление – явно закрыть файл. Пример с использованием контекстного менеджера:

```python
def main():
    # Закрывать файл явно при выходе из блока with
    with open(sys.argv[1]) as fp:
        nlines = len(fp.readlines())
    print(nlines)
```

Явное незакрытие ресурса может оставить его открытым намного дольше, чем ожидалось; это может вызвать серьёзные проблемы при выходе из Python. Это плохо в CPython, но ещё хуже в PyPy. Явное закрытие ресурсов делает приложение более детерминированным и надёжным.

# Пример ошибки «Bad file descriptor»

Сценарий, выводящий свою первую строку:

```python
import os

def main():
    fp = open(__file__)
    firstline = fp.readline()
    print(firstline.rstrip())
    os.close(fp.fileno())
    # Файл закрывается неявно

main()
```

По умолчанию Python не выводит никаких предупреждений:

```console
$ python3 script.py
import os
```

Режим разработки Python показывает [`ResourceWarning`](https://python-all.ru/3.9/library/exceptions.html#ResourceWarning) и регистрирует ошибку «Bad file descriptor» при финализации объекта файла:

```console
$ python3 script.py
import os
script.py:10: ResourceWarning: unclosed file <_io.TextIOWrapper name='script.py' mode='r' encoding='UTF-8'>
  main()
ResourceWarning: Enable tracemalloc to get the object allocation traceback
Exception ignored in: <_io.TextIOWrapper name='script.py' mode='r' encoding='UTF-8'>
Traceback (most recent call last):
  File "script.py", line 10, in <module>
    main()
OSError: [Errno 9] Bad file descriptor
```

`os.close(fp.fileno())` закрывает файловый дескриптор. Когда финализатор объекта файла пытается закрыть файловый дескриптор снова, это завершается ошибкой `Bad file descriptor`. Файловый дескриптор должен быть закрыт только один раз. В худшем случае повторное закрытие может привести к аварийному завершению (пример см. в [bpo-18748](https://python-all.ru/3.9/library/devmode.html)).

Исправление – удалить строку `os.close(fp.fileno())` или открыть файл с `closefd=False`.
