Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Lib/asyncio/coroutines.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def __init__(self, gen, func=None):
assert inspect.isgenerator(gen) or inspect.iscoroutine(gen), gen
self.gen = gen
self.func = func # Used to unwrap @coroutine decorator
self._source_traceback = traceback.extract_stack(sys._getframe(1))
self._source_traceback = events.extract_stack(sys._getframe(1))
self.__name__ = getattr(gen, '__name__', None)
self.__qualname__ = getattr(gen, '__qualname__', None)

Expand Down
20 changes: 19 additions & 1 deletion Lib/asyncio/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,24 @@ def _format_callback_source(func, args):
return func_repr


def extract_stack(f=None, limit=None):
"""Replacement for traceback.extract_stack() that only does the
necessary work for asyncio debug mode.
"""
if f is None:
f = sys._getframe().f_back
if limit is None:
# This is heuristically the max number of entries we're gonna pop + 1
# (we're only interested in displaying the top of stack)
# If this is too small, tests will fail.
limit = 4
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we bump this to 10? It's a debug mode after all, and seeing only 2-3 lines in traceback is sometimes not enough.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The traceback is never displayed. It's only used for Future.__repr__, which prints the line at which the future was created (i.e. the top-of-stack).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC Task.__del__ and CoroWrapper pass it to the loop's logger to print some debug info. In which case the full traceback would be printed to the user, no?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, yes, you're right. I agree with bumping to 10 then.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add it as a constant to asyncio/constants.py? Also, we need to update loop.default_exception_handler() method to say that we only display 10 topmost frames.

stack = traceback.StackSummary.extract(traceback.walk_stack(f),
limit=limit,
lookup_lines=False)
stack.reverse()
return stack


class Handle:
"""Object returned by callback registration methods."""

Expand All @@ -85,7 +103,7 @@ def __init__(self, callback, args, loop):
self._cancelled = False
self._repr = None
if self._loop.get_debug():
self._source_traceback = traceback.extract_stack(sys._getframe(1))
self._source_traceback = extract_stack(sys._getframe(1))
else:
self._source_traceback = None

Expand Down
2 changes: 1 addition & 1 deletion Lib/asyncio/futures.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def __init__(self, *, loop=None):
self._loop = loop
self._callbacks = []
if self._loop.get_debug():
self._source_traceback = traceback.extract_stack(sys._getframe(1))
self._source_traceback = events.extract_stack(sys._getframe(1))

_repr_info = base_futures._future_repr_info

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Reduce performance overhead of asyncio debug mode.