Spec-Zone.ru › Python 3.14

Режим разработки 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 проверяет, были ли корутины запущены без ожидания, и записывает такие случаи в журнал.

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

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

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

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

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

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

Режим разработки 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 ещё хуже. Явное закрытие ресурсов делает приложение более предсказуемым и надёжным.

Пример ошибки «Недопустимый файловый дескриптор»

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

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 и записывает в журнал ошибку «Недопустимый файловый дескриптор» при уничтожении файлового объекта:

$ 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 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.14/library/devmode.html

Spec-Zone.ru

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