Sitelet https://github.com/python/cpython/issues/105658
Skip to content

3.12 tracing regression: a conditional in a finally block will revisit the condition before exiting the block. #105658

Description

@nedbat

Python 3.12 introduced a change in tracing behavior. Now a conditional in a finally block will revisit the condition before exiting the block.

Here is test.py:

import sys
print(sys.version)

def example(raise_exc: bool, enter_finally_cond: bool):
    try:
        if raise_exc:
            print("raising exception")
            raise Exception
        print("not raising exception")
    finally:
        if enter_finally_cond:
            print("in finally conditional")

    print("after finally")

try:
    example(raise_exc=True, enter_finally_cond=True)
except:
    pass

When traced under 3.11:

% python3.11 -m trace --trace test.py
 --- modulename: test, funcname: <module>
test.py(1): import sys
test.py(2): print(sys.version)
3.11.4 (main, Jun  7 2023, 08:42:37) [Clang 14.0.3 (clang-1403.0.22.14.1)]
test.py(4): def example(raise_exc: bool, enter_finally_cond: bool):
test.py(16): try:
test.py(17):     example(raise_exc=True, enter_finally_cond=True)
 --- modulename: test, funcname: example
test.py(5):     try:
test.py(6):         if raise_exc:
test.py(7):             print("raising exception")
raising exception
test.py(8):             raise Exception
test.py(11):         if enter_finally_cond:
test.py(12):             print("in finally conditional")
in finally conditional
test.py(18): except:
test.py(19):     pass

When traced under 3.12:

% python3.12 -m trace --trace test.py
 --- modulename: test, funcname: <module>
test.py(1): import sys
test.py(2): print(sys.version)
3.12.0b2 (main, Jun  7 2023, 08:47:18) [Clang 14.0.3 (clang-1403.0.22.14.1)]
test.py(4): def example(raise_exc: bool, enter_finally_cond: bool):
test.py(16): try:
test.py(17):     example(raise_exc=True, enter_finally_cond=True)
 --- modulename: test, funcname: example
test.py(5):     try:
test.py(6):         if raise_exc:
test.py(7):             print("raising exception")
raising exception
test.py(8):             raise Exception
test.py(11):         if enter_finally_cond:
test.py(12):             print("in finally conditional")
in finally conditional
test.py(11):         if enter_finally_cond:             # <******
test.py(18): except:
test.py(19):     pass

The extra line is marked with <******. There's no reason for the if statement to be traced again.

Linked PRs

Activity

  1. added
    type-bugAn unexpected behavior, bug, or error
    on Jun 11, 2023
  2. Eclips4 commented on Jun 11, 2023

    @Eclips4
    Member

    Confirmed on current main branch

  3. Eclips4 commented on Jun 11, 2023

    @Eclips4
    Member

    Bisected to #98001, @nedbat can you confirm that?

  4. Eclips4 commented on Jun 11, 2023

    @Eclips4
    Member

    Why change of location is needed here?

    loc = location_of_last_executing_statement(s->v.Try.finalbody);

    I've deleted it(same for compiler_try_star_finally) and seems this fixes the issue, but I don't sure that's correct solution.

  5. self-assigned this
    on Jun 30, 2023
  6. added a commit that references this issue on Sep 1, 2023
  7. iritkatriel commented on Sep 13, 2023

    @iritkatriel
    Member

    Sorry, this dropped off my radar. I made a PR to remove the line number from these instructions (which are virtual).

  8. added 2 commits that reference this issue on Sep 14, 2023
  9. added a commit that references this issue on Sep 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

3.12only security fixes3.13only security fixestype-bugAn unexpected behavior, bug, or error

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions