python / python/cpython

`trace` function is cleared after `RecursionError` is fired

Abierto
#134,216 5 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

interpreter-core pending type-bug
Lenguaje dominante
Python
Estrellas
77.2k
Forks
35.9k
Métricas de merge de PR
Métricas de PR pendientes

Descripción

Bug report

Bug description:

I'm using coverage and pytest-cov in CI to measure the line coverage of the unittests. It is achieved by registering a trace function with sys.settrace.

However, after binsecting my unittests, I found that when a RecursionError is raised, the system trace function will be cleared. That will cause a warning emitted by coverage:

~/Projects/cpython/venv/lib/python3.15t/site-packages/coverage/pytracer.py:355: CoverageWarning: Trace function changed, data is likely wrong: None != <bound method PyTracer._trace of <PyTracer at 0x200021dcc20: 2076 data points in 11 files>> (trace-changed)
  self.warn(

Reproducible code:

import sys


def tracer(*args, **kwargs):
    pass


def factorial(n: int) -> int:
    """Calculate the factorial of a number."""
    if n <= 1:
        return 1
    return n * factorial(n - 1)


sys.settrace(tracer)
assert sys.gettrace() is tracer

sys.setrecursionlimit(64)
assert sys.gettrace() is tracer

try:
    _ = factorial(100)
except RecursionError:
    pass

assert sys.gettrace() is None

REPL Output:

# Add a code block here, if required
$ python3                      
Python 3.13.3 (main, Apr  8 2025, 13:54:08) [Clang 16.0.0 (clang-1600.0.26.6)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> def tracer(*args, **kwargs):
...     pass
... 
>>> def factorial(n):
...     if n <= 1:
...         return 1
...     return n * factorial(n - 1)
...     
>>> sys.settrace(tracer)
>>> sys.gettrace() is tracer
True
>>> sys.setrecursionlimit(64)
>>> _ = factorial(100)
Traceback (most recent call last):
  File "<python-input-6>", line 1, in <module>
    _ = factorial(100)
  File "<python-input-2>", line 4, in factorial
    return n * factorial(n - 1)
               ~~~~~~~~^^^^^^^
  File "<python-input-2>", line 4, in factorial
    return n * factorial(n - 1)
               ~~~~~~~~^^^^^^^
  File "<python-input-2>", line 4, in factorial
    return n * factorial(n - 1)
               ~~~~~~~~^^^^^^^
  [Previous line repeated 51 more times]
  File "<python-input-2>", line 1, in factorial
    def factorial(n):
    
RecursionError: maximum recursion depth exceeded
>>> sys.gettrace() is None
True
CPython versions tested on:

CPython main branch

Operating systems tested on:

macOS

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Ejecuta el reproducer proporcionado e inspecciona el comportamiento de sys.settrace, sys.gettrace y RecursionError en torno a la llamada recursiva a factorial. Rastrea las rutas de implementación de CPython implicadas en la gestión del límite de recursión y el tracing; se considera terminado cuando la función de tracing registrada sigue disponible después de RecursionError y existe cobertura de regresión para el reproducer.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
python
Área
compilers
Tipo de issue
Error
Dificultad
4/5
Tiempo estimado
3-5 días
Estado de actividad
Estancado
Claridad
Bastante claro
Aptitud para principiantes
45/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.