Режим разработки Python
Добавлен в версии 3.7.
Режим разработки Python добавляет дополнительные проверки во время выполнения, которые слишком затратны для включения по умолчанию. Он не должен быть более подробным, чем по умолчанию, если код корректен; новые предупреждения отображаются только при обнаружении проблемы.
Его можно включить с помощью опции командной строки -X dev или установив переменную среды PYTHONDEVMODE в значение 1.
См. также Отладочная сборка Python.
Эффекты режима разработки Python
Включение режима разработки Python аналогично следующей команде, но с дополнительными эффектами, описанными ниже:
PYTHONMALLOC=debug PYTHONASYNCIODEBUG=1 python -W default -X faulthandler
Эффекты режима разработки Python:
-
Добавляет
defaultфильтр предупреждений. Отображаются следующие предупреждения:Обычно вышеперечисленные предупреждения отфильтровываются стандартными фильтрами предупреждений.
Это эквивалентно использованию опции командной строки
-W default.Используйте опцию командной строки
-W errorили установите переменную средыPYTHONWARNINGSв значениеerrorдля обработки предупреждений как ошибок. -
Устанавливает отладочные крючки на менеджеры памяти для проверки:
- Недопустимого уменьшения буфера
- Недопустимого увеличения буфера
- Нарушения API менеджера памяти
- Небезопасного использования GIL
См. функцию C
PyMem_SetupDebugHooks().Это эквивалентно установке переменной среды
PYTHONMALLOCв значениеdebug.Чтобы включить режим разработки Python без установки отладочных крючков на менеджеры памяти, установите переменную среды
PYTHONMALLOCв значениеdefault. -
Вызывает
faulthandler.enable()при запуске Python для установки обработчиков сигналов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 не препятствует опции командной строки -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–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/library/devmode.html