python / python/cpython

Allow top-level statements in a global pre-setup phase for `timeit`

Abierto
#137,578 7 comentarios 0 reacciones 1 asignado Ver en GitHub

@picnixz ya está trabajando en esto.

Desde el 9/8/2025.

stdlib type-feature
Lenguaje dominante
Python
Estrellas
77.2k
Forks
36k
Métricas de merge de PR
Métricas de PR pendientes

Descripción

Bug report

Bug description:

timeit crashes when using wildcard imports in either the "setup" or "statement" fields.

$ python -m timeit -s "from collections import Counter" -- "Counter([1, 2])" # allowed
1000000 loops, best of 5: 277 nsec per loop
$ python -m timeit -s "from collections import *" -- "Counter([1, 2])" # cashes
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "Lib/timeit.py", line 378, in <module>
    sys.exit(main())
             ~~~~^^
  File "Lib/timeit.py", line 316, in main
    t = Timer(stmt, setup, timer)
  File "Lib/timeit.py", line 132, in __init__
    code = compile(src, dummy_src_name, "exec")
  File "<timeit-src>", line 3
SyntaxError: import * only allowed at module level

This is surprising as this syntax is allowed in other contexts where code strings are executed (namely exec and python -c). The cause is code strings are placed inside a wrapper function that performs the timing here.

The git history of the timeit tests show 2bef58577f1caa293a4843f4bdf245407825a61a explicitly added a test for this behavior, but based on the commit message / corresponding issue (GH #62718) I'm not sure if this is indeed the intended behavior. The comments seem to focus on statements that would effect a timing result (e.g., break ending a loop early or return changing the timed value), which I don't think applies to wild card imports.

Extra history: #46779 discussed this briefly in the context of from __main__ import * and the performance implications of wildcard imports when namespace arguments were first introduced.

Allowing wildcard imports in both stages would be great to bring unity with the other exec-likes and make CLI usage nicer, but the argument for statement is weaker than setup.

Potential options

  1. move setup to outside inner and update globals and locals to be the same when exec is called on the code-object.
    • doesn't allow wildcards in statement
    • any variable created in setup requires a global namespace lookup which adds overhead
    • setup would be ran exactly once, so breaks methods that repeat with randomization
  2. remove inner and instead call exec where inner was called, and either move the timing code bits to outside exec or extract the timed value from the exec namespace.
    • supports wildcard imports in both code strings
    • variable access seems to be through LOAD_NAME instead of LOAD_FAST which may have a overhead?
    • significantly more invasive to the existing code
  3. do nothing and leave the mismatch. PEP8 / the docs discourage wildcard imports anyway.
CPython versions tested on:

CPython main branch

Operating systems tested on:

macOS

Linked PRs
  • gh-137587

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.

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.