Spec-Zone.ru › Python 3.13

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

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

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

Его можно включить с помощью параметра командной строки -X dev или установив переменную окружения PYTHONDEVMODE в значение 1.

См. также Отладочную сборку Python.

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

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

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

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

  • Добавляет default фильтр предупреждений. Выводятся следующие предупреждения:

    • DeprecationWarning
    • ImportWarning
    • PendingDeprecationWarning
    • ResourceWarning

    Обычно перечисленные выше предупреждения отфильтровываются стандартными фильтрами предупреждений.

    Поведение такое же, как при использовании параметра командной строки -W default.

    Используйте параметр командной строки -W error или установите переменную окружения PYTHONWARNINGS в значение error, чтобы считать предупреждения ошибками.

  • Устанавливает отладочные перехватчики для распределителей памяти, чтобы обнаруживать:

    • Чтение за пределами буфера
    • Запись за пределами буфера
    • Нарушение правил использования API распределителя памяти
    • Небезопасное использование GIL

    См. функцию C PyMem_SetupDebugHooks().

    Поведение такое же, как если бы переменная окружения PYTHONMALLOC была установлена в значение debug.

    Чтобы включить режим разработки Python без установки отладочных перехватчиков для распределителей памяти, установите переменную окружения PYTHONMALLOC в значение default.

  • При запуске Python вызывает faulthandler.enable(), чтобы установить обработчики сигналов SIGSEGV, SIGFPE, SIGABRT, SIGBUS и SIGILL, которые при сбое выводят трассировку стека Python.

    Поведение такое же, как при использовании параметра командной строки -X faulthandler или если переменная окружения PYTHONFAULTHANDLER установлена в значение 1.

  • Включает режим отладки asyncio. Например, asyncio обнаруживает корутины, которые не были запущены с помощью await, и записывает информацию о них в журнал.

    Поведение такое же, как если бы переменная окружения PYTHONASYNCIODEBUG была установлена в значение 1.

  • Проверяет аргументы encoding и errors для операций кодирования и декодирования строк. Например: open(), str.encode() и bytes.decode().

    По умолчанию, для повышения производительности, аргумент errors проверяется только при первой ошибке кодирования или декодирования, а аргумент encoding иногда игнорируется для пустых строк.

  • Деструктор io.IOBase записывает исключения close() в журнал.
  • Устанавливает атрибут dev_mode объекта sys.flags в значение True.

Режим разработки Python не включает по умолчанию модуль tracemalloc, поскольку связанные с ним накладные расходы (на производительность и память) были бы слишком велики. Включение модуля tracemalloc предоставляет дополнительные сведения о происхождении некоторых ошибок. Например, при возникновении ResourceWarning в журнал записывается трассировка стека в месте выделения ресурса, а при переполнении буфера — трассировка стека в месте выделения блока памяти.

Режим разработки Python не мешает параметру командной строки -O удалять инструкции assert и устанавливать __debug__ в значение False.

Режим разработки Python можно включить только при запуске Python. Его значение можно прочитать из sys.flags.dev_mode.

Изменено в версии 3.8: Теперь деструктор io.IOBase записывает исключения close() в журнал.

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

Пример ResourceWarning

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

import sys

def main():
    fp = open(sys.argv[1])
    nlines = len(fp.readlines())
    print(nlines)
    # The file is closed implicitly

if __name__ == "__main__":
    main()

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

$ python script.py README.txt
269

При включении режима разработки Python выводится предупреждение ResourceWarning:

$ python -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 показывает строку, в которой был открыт файл:

$ python -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])

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

def main():
    # Close the file explicitly when exiting the with block
    with open(sys.argv[1]) as fp:
        nlines = len(fp.readlines())
    print(nlines)

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

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

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

import os

def main():
    fp = open(__file__)
    firstline = fp.readline()
    print(firstline.rstrip())
    os.close(fp.fileno())
    # The file is closed implicitly

main()

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

$ python script.py
import os

В режиме разработки Python выводится предупреждение ResourceWarning, а при финализации файлового объекта в журнал записывается ошибка «Bad file descriptor»:

$ python -X dev 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).

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

© 2001–2025 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/library/devmode.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API