Python Development ModePython开发模式¶
New in version 3.7.版本3.7中新增。
The Python Development Mode introduces additional runtime checks that are too expensive to be enabled by default. Python开发模式引入了额外的运行时检查,这些检查过于昂贵,无法在默认情况下启用。It should not be more verbose than the default if the code is correct; new warnings are only emitted when an issue is detected.如果代码是正确的,那么它不应该比默认值更详细;只有在检测到问题时才会发出新的警告。
It can be enabled using the 它可以使用-X dev
command line option or by setting the PYTHONDEVMODE
environment variable to 1
.-X dev
命令行选项或通过将PYTHONDEVMODE
环境变量设置为1来启用。
See also Python debug build.另请参见Python调试构建。
Effects of the Python Development ModePython开发模式的影响¶
Enabling the Python Development Mode is similar to the following command, but with additional effects described below:启用Python开发模式类似于以下命令,但具有以下所述的附加效果:
PYTHONMALLOC=debug PYTHONASYNCIODEBUG=1 python3 -W default -X faulthandler
Effects of the Python Development Mode:Python开发模式的影响:
Add添加default
warning filter.default
警告筛选器。The following warnings are shown:显示以下警告:Normally, the above warnings are filtered by the default warning filters.通常情况下,上述警告由默认的警告筛选器进行过滤。It behaves as if the它的行为就像使用了-W default
command line option is used.-W default
命令行选项一样。Use the
-W error
command line option or set thePYTHONWARNINGS
environment variable toerror
to treat warnings as errors.Install debug hooks on memory allocators to check for:在内存分配器上安装调试挂钩以检查:Buffer underflow
Buffer overflow
Memory allocator API violation
Unsafe usage of the GIL
See the
PyMem_SetupDebugHooks()
C function.It behaves as if the
PYTHONMALLOC
environment variable is set todebug
.To enable the Python Development Mode without installing debug hooks on memory allocators, set the
PYTHONMALLOC
environment variable todefault
.Call
faulthandler.enable()
at Python startup to install handlers for theSIGSEGV
,SIGFPE
,SIGABRT
,SIGBUS
andSIGILL
signals to dump the Python traceback on a crash.It behaves as if the
-X faulthandler
command line option is used or if thePYTHONFAULTHANDLER
environment variable is set to1
.Enable asyncio debug mode. For example,
asyncio
checks for coroutines that were not awaited and logs them.It behaves as if the
PYTHONASYNCIODEBUG
environment variable is set to1
.Check the encoding and errors arguments for string encoding and decoding operations. Examples:
open()
,str.encode()
andbytes.decode()
.By default, for best performance, the errors argument is only checked at the first encoding/decoding error and the encoding argument is sometimes ignored for empty strings.
The
io.IOBase
destructor logsclose()
exceptions.Set the将dev_mode
attribute ofsys.flags
toTrue
.sys.flags
的dev_mode
属性设置为True
。
The Python Development Mode does not enable the Python开发模式默认情况下不启用tracemalloc
module by default, because the overhead cost (to performance and memory) would be too large. tracemalloc
模块,因为开销(性能和内存)太大。Enabling the 启用tracemalloc
module provides additional information on the origin of some errors. tracemalloc
模块可以提供有关某些错误来源的其他信息。For example, 例如,ResourceWarning
logs the traceback where the resource was allocated, and a buffer overflow error logs the traceback where the memory block was allocated.ResourceWarning
记录分配资源的回溯,缓冲区溢出错误记录分配内存块的回溯。
The Python Development Mode does not prevent the Python开发模式不会阻止-O
command line option from removing assert
statements nor from setting __debug__
to False
.-O
命令行选项删除assert
语句,也不会阻止将__debug__
设置为False
。
The Python Development Mode can only be enabled at the Python startup. Python开发模式只能在Python启动时启用。Its value can be read from 其值可以从sys.flags.dev_mode
.sys.flags.dev_mode
中读取。
Changed in version 3.8:版本3.8中更改: The io.IOBase
destructor now logs close()
exceptions.io.IOBase
析构函数现在记录close()
异常。
Changed in version 3.9:版本3.9中更改: The encoding and errors arguments are now checked for string encoding and decoding operations.现在检查encoding和errors参数以进行字符串编码和解码操作。
ResourceWarning Example资源警告示例¶
Example of a script counting the number of lines of the text file specified in the command line:计算命令行中指定的文本文件的行数的脚本示例:
import sys
def main():
fp = open(sys.argv[1])
nlines = len(fp.readlines())
print(nlines)
# The file is closed implicitly
if __name__ == "__main__":
main()
The script does not close the file explicitly. 脚本没有显式关闭文件。By default, Python does not emit any warning. 默认情况下,Python不会发出任何警告。Example using README.txt, which has 269 lines:使用READMEtxt的示例,它有269行:
$ python3 script.py README.txt
269
Enabling the Python Development Mode displays a 启用Python开发模式会显示ResourceWarning
warning:ResourceWarning
警告:
$ 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
In addition, enabling 此外,启用tracemalloc
shows the line where the file was opened:tracemalloc
会显示打开文件的行:
$ 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])
The fix is to close explicitly the file. Example using a context manager:解决方法是显式关闭该文件。使用上下文管理器的示例:
def main():
# Close the file explicitly when exiting the with block
with open(sys.argv[1]) as fp:
nlines = len(fp.readlines())
print(nlines)
Not closing a resource explicitly can leave a resource open for way longer than expected; it can cause severe issues upon exiting Python. 不显式关闭资源可能会使资源的打开时间比预期的要长得多;退出Python时可能会导致严重问题。It is bad in CPython, but it is even worse in PyPy. CPython的情况很糟糕,但PyPy的情况更糟。Closing resources explicitly makes an application more deterministic and more reliable.明确地关闭资源会使应用程序更具确定性和可靠性。
Bad file descriptor error example错误的文件描述符错误示例¶
Script displaying the first line of itself:显示自身第一行的脚本:
import os
def main():
fp = open(__file__)
firstline = fp.readline()
print(firstline.rstrip())
os.close(fp.fileno())
# The file is closed implicitly
main()
By default, Python does not emit any warning:默认情况下,Python不会发出任何警告:
$ python3 script.py
import os
The Python Development Mode shows a Python开发模式在完成文件对象时显示ResourceWarning
and logs a “Bad file descriptor” error when finalizing the file object:ResourceWarning
并记录“Bad file descriptor”错误:
$ 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())
closes the file descriptor. 关闭文件描述符。When the file object finalizer tries to close the file descriptor again, it fails with the 当文件对象终结器再次尝试关闭文件描述符时,它将失败,并出现Bad file descriptor
error. Bad file descriptor
错误。A file descriptor must be closed only once. 文件描述符只能关闭一次。In the worst case scenario, closing it twice can lead to a crash (see bpo-18748 for an example).在最坏的情况下,关闭两次可能会导致崩溃(例如,请参阅bpo-18748)。
The fix is to remove the 修复方法是删除os.close(fp.fileno())
line, or open the file with closefd=False
.os.close(fp.fileno())
行,或者用closefd=False
打开文件。