python / python/cpython

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

Ouverte
#137,578 7 commentaires 0 réactions 1 personne assignée Voir sur GitHub

@picnixz y travaille déjà.

Depuis le 9/8/2025.

stdlib type-feature
Langage dominant
Python
Étoiles
77.2k
Forks
36k
Métriques de merge des PR
Métriques de PR en attente

Description

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

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Évaluation

Cette issue n'a pas encore été évaluée.

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.