Skip to content

line with "with" should not be on the stacktrace for exceptions raised in __exit__ #126932

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
vanschelven opened this issue Nov 17, 2024 · 3 comments
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error

Comments

@vanschelven
Copy link

vanschelven commented Nov 17, 2024

Bug report

Bug description:

When an exception happens in the __exit__ part of a context manager, the
with ... line is part of the stacktrace. This is surprising (in the bad
way), because that line is not a part of the stacktrace while you're in the
associated block of code.

In other words: at the end (either the premature end through an exception, or
when the end of the end of the block is reached) the frame for the with
statements gets pushed onto the traceback. Even though at that time nothing
from that line is being executed.

What I find particularly confusing (wrong?) is that this approach is suggestive
of the fact that code from the line of the with statement is being executed
at the time of of failure.

OTOH, I kinda understand why the line is there: it's to explain why one arrives
at __exit__. But that's not really through that line, it's more indirectly
through something like "exiting the with statement from line xx". (in the clean
exit case, this would arguable be at the end of the block).

Some example code and tracebacks:

knockknock

# knockknock.py  -- this demonstrates the weridness of 'with' showing up
class Context:

    def __enter__(self):
        pass

    def __exit__(self, exc_type, exc_value, traceback):
        raise Exception("Who's there? One line too many?")


def function_that_fails():
    with Context():
        pass


function_that_fails()
$ python knockknock.py 
Traceback (most recent call last):
  File "knockknock.py", line 16, in <module>
    function_that_fails()
  File "knockknock.py", line 12, in function_that_fails     <= what's this doing here?
    with Context():                                         <= what's this doing here?
  File "knockknock.py", line 8, in __exit__
    raise Exception("Who's there? One line too many?")
Exception: Who's there? One line too many?

Compare this with an exception inside a with-statement, where the __exit__ itself is without problems.

nobody

# nobody.py -- shows that if an exception is raised inside the context manager, the line "with" does _not_ show up
class Context:

    def __enter__(self):
        pass

    def __exit__(self, exc_type, exc_value, traceback):
        pass


def function_that_fails():
    with Context():
        raise Exception("No frame for the Context this time")


function_that_fails()
$ python nobody.py 
Traceback (most recent call last):
  File "nobody.py", line 16, in <module>
    function_that_fails()
  File "nobody.py", line 13, in function_that_fails
    raise Exception("No frame for the Context this time")
Exception: No frame for the Context this time

I'm going to call this a bug because I have no way of (concisely) explaining why
this would be the correct behavior. In general, this would be my explanation of
a stacktrace:

A stacktrace shows the sequence of function calls that led to a
specific point in a program, where each line corresponds to a function call,
including its location in the code.

This explanation breaks down for the above. Could it be amended without (at least)
doubling in length?

CPython versions tested on:

3.10, 3.12

Operating systems tested on:

Linux

@vanschelven vanschelven added the type-bug An unexpected behavior, bug, or error label Nov 17, 2024
@Alleycat907ak

This comment was marked as spam.

@audionai
Copy link

audionai commented Nov 17, 2024

The with statement showing up in the stack trace for __exit__ exceptions is a @documented behavior.
While it can be confusing, it offers context for debugging.

@vanschelven
Copy link
Author

"documented"

I think you tried to link to some piece of documentation there but that link leads nowhere, and I cannot find the documentation myself (I looked for it before filing this bug)

@picnixz picnixz added the interpreter-core (Objects, Python, Grammar, and Parser dirs) label Nov 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

4 participants