mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	
		
			
	
	
		
			215 lines
		
	
	
	
		
			7.1 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
		
		
			
		
	
	
			215 lines
		
	
	
	
		
			7.1 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| 
								 | 
							
								.. _devmode:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Python Development Mode
							 | 
						||
| 
								 | 
							
								=======================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								.. versionadded:: 3.7
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The Python Development Mode introduces additional runtime checks that are too
							 | 
						||
| 
								 | 
							
								expensive to be enabled by default. 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 :option:`-X dev <-X>` command line option or by
							 | 
						||
| 
								 | 
							
								setting the :envvar:`PYTHONDEVMODE` environment variable to ``1``.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Effects of the Python Development Mode
							 | 
						||
| 
								 | 
							
								======================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Enabling the Python Development Mode is similar to the following command, but
							 | 
						||
| 
								 | 
							
								with additional effects described below::
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    PYTHONMALLOC=debug PYTHONASYNCIODEBUG=1 python3 -W default -X faulthandler
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Effects of the Python Development Mode:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* Add ``default`` :ref:`warning filter <describing-warning-filters>`. The
							 | 
						||
| 
								 | 
							
								  following warnings are shown:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  * :exc:`DeprecationWarning`
							 | 
						||
| 
								 | 
							
								  * :exc:`ImportWarning`
							 | 
						||
| 
								 | 
							
								  * :exc:`PendingDeprecationWarning`
							 | 
						||
| 
								 | 
							
								  * :exc:`ResourceWarning`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Normally, the above warnings are filtered by the default :ref:`warning
							 | 
						||
| 
								 | 
							
								  filters <describing-warning-filters>`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  It behaves as if the :option:`-W default <-W>` command line option is used.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Use the :option:`-W error <-W>` command line option or set the
							 | 
						||
| 
								 | 
							
								  :envvar:`PYTHONWARNINGS` environment variable to ``error`` 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 :c:func:`PyMem_SetupDebugHooks` C function.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  It behaves as if the :envvar:`PYTHONMALLOC` environment variable is set to
							 | 
						||
| 
								 | 
							
								  ``debug``.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  To enable the Python Development Mode without installing debug hooks on
							 | 
						||
| 
								 | 
							
								  memory allocators, set the :envvar:`PYTHONMALLOC` environment variable to
							 | 
						||
| 
								 | 
							
								  ``default``.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* Call :func:`faulthandler.enable` at Python startup to install handlers for
							 | 
						||
| 
								 | 
							
								  the :const:`SIGSEGV`, :const:`SIGFPE`, :const:`SIGABRT`, :const:`SIGBUS` and
							 | 
						||
| 
								 | 
							
								  :const:`SIGILL` signals to dump the Python traceback on a crash.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  It behaves as if the :option:`-X faulthandler <-X>` command line option is
							 | 
						||
| 
								 | 
							
								  used or if the :envvar:`PYTHONFAULTHANDLER` environment variable is set to
							 | 
						||
| 
								 | 
							
								  ``1``.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* Enable :ref:`asyncio debug mode <asyncio-debug-mode>`. For example,
							 | 
						||
| 
								 | 
							
								  :mod:`asyncio` checks for coroutines that were not awaited and logs them.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  It behaves as if the :envvar:`PYTHONASYNCIODEBUG` environment variable is set
							 | 
						||
| 
								 | 
							
								  to ``1``.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* Check the *encoding* and *errors* arguments for string encoding and decoding
							 | 
						||
| 
								 | 
							
								  operations. Examples: :func:`open`, :meth:`str.encode` and
							 | 
						||
| 
								 | 
							
								  :meth:`bytes.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 :class:`io.IOBase` destructor logs ``close()`` exceptions.
							 | 
						||
| 
								 | 
							
								* Set the :attr:`~sys.flags.dev_mode` attribute of :attr:`sys.flags` to
							 | 
						||
| 
								 | 
							
								  ``True``.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The Python Development Mode does not enable the :mod:`tracemalloc` module by
							 | 
						||
| 
								 | 
							
								default, because the overhead cost (to performance and memory) would be too
							 | 
						||
| 
								 | 
							
								large. Enabling the :mod:`tracemalloc` module provides additional information
							 | 
						||
| 
								 | 
							
								on the origin of some errors. For example, :exc:`ResourceWarning` logs the
							 | 
						||
| 
								 | 
							
								traceback where the resource was allocated, and a buffer overflow error logs
							 | 
						||
| 
								 | 
							
								the traceback where the memory block was allocated.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The Python Development Mode does not prevent the :option:`-O` command line
							 | 
						||
| 
								 | 
							
								option from removing :keyword:`assert` statements nor from setting
							 | 
						||
| 
								 | 
							
								:const:`__debug__` to ``False``.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								.. versionchanged:: 3.8
							 | 
						||
| 
								 | 
							
								   The :class:`io.IOBase` destructor now logs ``close()`` exceptions.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								.. versionchanged:: 3.9
							 | 
						||
| 
								 | 
							
								   The *encoding* and *errors* arguments are now checked for string encoding
							 | 
						||
| 
								 | 
							
								   and decoding operations.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								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. Example using README.txt, which has 269 lines:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								.. code-block:: shell-session
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $ python3 script.py README.txt
							 | 
						||
| 
								 | 
							
								    269
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Enabling the Python Development Mode displays a :exc:`ResourceWarning` warning:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								.. code-block:: shell-session
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $ 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 :mod:`tracemalloc` shows the line where the file was
							 | 
						||
| 
								 | 
							
								opened:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								.. code-block:: shell-session
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $ 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. It is bad in
							 | 
						||
| 
								 | 
							
								CPython, but it is even worse in 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:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								.. code-block:: shell-session
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $ python3 script.py
							 | 
						||
| 
								 | 
							
								    import os
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The Python Development Mode shows a :exc:`ResourceWarning` and logs a "Bad file
							 | 
						||
| 
								 | 
							
								descriptor" error when finalizing the file object:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								.. code-block:: shell-session
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $ 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. A file descriptor must be closed only once. In the
							 | 
						||
| 
								 | 
							
								worst case scenario, closing it twice can lead to a crash (see :issue:`18748`
							 | 
						||
| 
								 | 
							
								for an example).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The fix is to remove the ``os.close(fp.fileno())`` line, or open the file with
							 | 
						||
| 
								 | 
							
								``closefd=False``.
							 |