Allow top-level statements in a global pre-setup phase for `timeit`
@picnixz 已經在處理了。
開始於 2025年8月9日。
- 主要語言
- Python
- 星號
- 77.2k
- 分支
- 35.9k
- PR 合併指標
- PR 指標待擷取
描述
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
- move
setupto outsideinnerand updateglobalsandlocalsto be the same whenexecis called on the code-object.- doesn't allow wildcards in
statement - any variable created in setup requires a global namespace lookup which adds overhead
setupwould be ran exactly once, so breaks methods that repeat with randomization
- doesn't allow wildcards in
- remove
innerand instead callexecwhereinnerwas called, and either move the timing code bits to outsideexecor extract the timed value from theexecnamespace.- supports wildcard imports in both code strings
- variable access seems to be through
LOAD_NAMEinstead ofLOAD_FASTwhich may have a overhead? - significantly more invasive to the existing code
- 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
貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
評估
這個 Issue 還沒有評估資料。