Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion Doc/library/asyncio-dev.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ enable *debug mode*.
To enable all debug checks for an application:

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

.. versionchanged:: 3.7

The new ``-X dev`` command line option can now also be used to enable
the debug mode.

.. seealso::

The :meth:`AbstractEventLoop.set_debug` method and the :ref:`asyncio logger
Expand Down
10 changes: 6 additions & 4 deletions Doc/using/cmdline.rst
Original file line number Diff line number Diff line change
Expand Up @@ -414,16 +414,18 @@ Miscellaneous options
application. Typical usage is ``python3 -X importtime -c 'import
asyncio'``. See also :envvar:`PYTHONPROFILEIMPORTTIME`.
* ``-X dev`` enables the "developer mode": enable debug checks at runtime.
In short, ``python3 -X dev ...`` behaves as ``PYTHONMALLOC=debug python3
In short, ``python3 -X dev ...`` behaves as ``PYTHONMALLOC=debug PYTHONASYNCIODEBUG=1 python3
-W default -X faulthandler ...``, except that the :envvar:`PYTHONMALLOC`
environment variable is not set in practice. Developer mode:
and :envvar:`PYTHONASYNCIODEBUG` environment variables are not set in
practice. Developer mode:

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

It also allows passing arbitrary values and retrieving them through the
:data:`sys._xoptions` dictionary.
Expand Down
3 changes: 1 addition & 2 deletions Lib/asyncio/base_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,7 @@ def __init__(self):
self._thread_id = None
self._clock_resolution = time.get_clock_info('monotonic').resolution
self._exception_handler = None
self.set_debug((not sys.flags.ignore_environment
and bool(os.environ.get('PYTHONASYNCIODEBUG'))))
self.set_debug(coroutines._is_debug_mode())
# In debug mode, if the execution of a callback or a step of a task
# exceed this duration in seconds, the slow callback/task is logged.
self.slow_callback_duration = 0.1
Expand Down
30 changes: 19 additions & 11 deletions Lib/asyncio/coroutines.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,25 @@
# Opcode of "yield from" instruction
_YIELD_FROM = opcode.opmap['YIELD_FROM']

# If you set _DEBUG to true, @coroutine will wrap the resulting
# generator objects in a CoroWrapper instance (defined below). That
# instance will log a message when the generator is never iterated
# over, which may happen when you forget to use "yield from" with a
# coroutine call. Note that the value of the _DEBUG flag is taken
# when the decorator is used, so to be of any use it must be set
# before you define your coroutines. A downside of using this feature
# is that tracebacks show entries for the CoroWrapper.__next__ method
# when _DEBUG is true.
_DEBUG = (not sys.flags.ignore_environment and
bool(os.environ.get('PYTHONASYNCIODEBUG')))

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


_DEBUG = _is_debug_mode()


try:
Expand Down
4 changes: 4 additions & 0 deletions Lib/test/test_asyncio/test_base_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,10 @@ def test_env_var_debug(self):
PYTHONASYNCIODEBUG='1')
self.assertEqual(stdout.rstrip(), b'False')

sts, stdout, stderr = assert_python_ok('-E', '-X', 'dev',
'-c', code)
self.assertEqual(stdout.rstrip(), b'True')

def test_create_task(self):
class MyTask(asyncio.Task):
pass
Expand Down
4 changes: 4 additions & 0 deletions Lib/test/test_asyncio/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2350,6 +2350,10 @@ def test_env_var_debug(self):
PYTHONPATH=aio_path)
self.assertEqual(stdout.rstrip(), b'False')

sts, stdout, stderr = assert_python_ok('-E', '-X', 'dev',
'-c', code)
self.assertEqual(stdout.rstrip(), b'True')


class FutureGatherTests(GatherTestsBase, test_utils.TestCase):

Expand Down