Skip to content

Commit 44862df

Browse files
authored
bpo-32047: -X dev enables asyncio debug mode (#4418)
The new -X dev command line option now also enables asyncio debug mode.
1 parent 04dee27 commit 44862df

File tree

6 files changed

+42
-18
lines changed

6 files changed

+42
-18
lines changed

Doc/library/asyncio-dev.rst

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ enable *debug mode*.
2121
To enable all debug checks for an application:
2222

2323
* Enable the asyncio debug mode globally by setting the environment variable
24-
:envvar:`PYTHONASYNCIODEBUG` to ``1``, or by calling :meth:`AbstractEventLoop.set_debug`.
24+
:envvar:`PYTHONASYNCIODEBUG` to ``1``, using ``-X dev`` command line option
25+
(see the :option:`-X` option), or by calling
26+
:meth:`AbstractEventLoop.set_debug`.
2527
* Set the log level of the :ref:`asyncio logger <asyncio-logger>` to
2628
:py:data:`logging.DEBUG`. For example, call
2729
``logging.basicConfig(level=logging.DEBUG)`` at startup.
@@ -42,6 +44,11 @@ Examples debug checks:
4244
* :exc:`ResourceWarning` warnings are emitted when transports and event loops
4345
are :ref:`not closed explicitly <asyncio-close-transports>`.
4446

47+
.. versionchanged:: 3.7
48+
49+
The new ``-X dev`` command line option can now also be used to enable
50+
the debug mode.
51+
4552
.. seealso::
4653

4754
The :meth:`AbstractEventLoop.set_debug` method and the :ref:`asyncio logger

Doc/using/cmdline.rst

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -414,16 +414,18 @@ Miscellaneous options
414414
application. Typical usage is ``python3 -X importtime -c 'import
415415
asyncio'``. See also :envvar:`PYTHONPROFILEIMPORTTIME`.
416416
* ``-X dev`` enables the "developer mode": enable debug checks at runtime.
417-
In short, ``python3 -X dev ...`` behaves as ``PYTHONMALLOC=debug python3
417+
In short, ``python3 -X dev ...`` behaves as ``PYTHONMALLOC=debug PYTHONASYNCIODEBUG=1 python3
418418
-W default -X faulthandler ...``, except that the :envvar:`PYTHONMALLOC`
419-
environment variable is not set in practice. Developer mode:
419+
and :envvar:`PYTHONASYNCIODEBUG` environment variables are not set in
420+
practice. Developer mode:
420421

421422
* Add ``default`` warnings option. For example, display
422423
:exc:`DeprecationWarning` and :exc:`ResourceWarning` warnings.
423-
* Install debug hooks on memory allocators as if :envvar:`PYTHONMALLOC`
424-
is set to ``debug``.
424+
* Install debug hooks on memory allocators: see the
425+
:c:func:`PyMem_SetupDebugHooks` C function.
425426
* Enable the :mod:`faulthandler` module to dump the Python traceback
426427
on a crash.
428+
* Enable :ref:`asyncio debug mode <asyncio-debug-mode>`.
427429

428430
It also allows passing arbitrary values and retrieving them through the
429431
:data:`sys._xoptions` dictionary.

Lib/asyncio/base_events.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,7 @@ def __init__(self):
244244
self._thread_id = None
245245
self._clock_resolution = time.get_clock_info('monotonic').resolution
246246
self._exception_handler = None
247-
self.set_debug((not sys.flags.ignore_environment
248-
and bool(os.environ.get('PYTHONASYNCIODEBUG'))))
247+
self.set_debug(coroutines._is_debug_mode())
249248
# In debug mode, if the execution of a callback or a step of a task
250249
# exceed this duration in seconds, the slow callback/task is logged.
251250
self.slow_callback_duration = 0.1

Lib/asyncio/coroutines.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,25 @@
1919
# Opcode of "yield from" instruction
2020
_YIELD_FROM = opcode.opmap['YIELD_FROM']
2121

22-
# If you set _DEBUG to true, @coroutine will wrap the resulting
23-
# generator objects in a CoroWrapper instance (defined below). That
24-
# instance will log a message when the generator is never iterated
25-
# over, which may happen when you forget to use "yield from" with a
26-
# coroutine call. Note that the value of the _DEBUG flag is taken
27-
# when the decorator is used, so to be of any use it must be set
28-
# before you define your coroutines. A downside of using this feature
29-
# is that tracebacks show entries for the CoroWrapper.__next__ method
30-
# when _DEBUG is true.
31-
_DEBUG = (not sys.flags.ignore_environment and
32-
bool(os.environ.get('PYTHONASYNCIODEBUG')))
22+
23+
def _is_debug_mode():
24+
# If you set _DEBUG to true, @coroutine will wrap the resulting
25+
# generator objects in a CoroWrapper instance (defined below). That
26+
# instance will log a message when the generator is never iterated
27+
# over, which may happen when you forget to use "yield from" with a
28+
# coroutine call. Note that the value of the _DEBUG flag is taken
29+
# when the decorator is used, so to be of any use it must be set
30+
# before you define your coroutines. A downside of using this feature
31+
# is that tracebacks show entries for the CoroWrapper.__next__ method
32+
# when _DEBUG is true.
33+
debug = (not sys.flags.ignore_environment and
34+
bool(os.environ.get('PYTHONASYNCIODEBUG')))
35+
if hasattr(sys, '_xoptions') and 'dev' in sys._xoptions:
36+
debug = True
37+
return debug
38+
39+
40+
_DEBUG = _is_debug_mode()
3341

3442

3543
try:

Lib/test/test_asyncio/test_base_events.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,10 @@ def test_env_var_debug(self):
822822
PYTHONASYNCIODEBUG='1')
823823
self.assertEqual(stdout.rstrip(), b'False')
824824

825+
sts, stdout, stderr = assert_python_ok('-E', '-X', 'dev',
826+
'-c', code)
827+
self.assertEqual(stdout.rstrip(), b'True')
828+
825829
def test_create_task(self):
826830
class MyTask(asyncio.Task):
827831
pass

Lib/test/test_asyncio/test_tasks.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2350,6 +2350,10 @@ def test_env_var_debug(self):
23502350
PYTHONPATH=aio_path)
23512351
self.assertEqual(stdout.rstrip(), b'False')
23522352

2353+
sts, stdout, stderr = assert_python_ok('-E', '-X', 'dev',
2354+
'-c', code)
2355+
self.assertEqual(stdout.rstrip(), b'True')
2356+
23532357

23542358
class FutureGatherTests(GatherTestsBase, test_utils.TestCase):
23552359

0 commit comments

Comments
 (0)