Title: argparse performance regression in 3.14+ due to colorization overhead · Issue #142267 · python/cpython · GitHub
Open Graph Title: argparse performance regression in 3.14+ due to colorization overhead · Issue #142267 · python/cpython
X Title: argparse performance regression in 3.14+ due to colorization overhead · Issue #142267 · python/cpython
Description: I spent some time running the argparse bm_subparsers benchmark from pyperformance (1000 optional arguments, 10 iterations) Version Time Function Calls 3.10 0.585s 560K 3.11 0.207s 560K 3.12 0.229s 560K 3.13 0.246s 560K 3.14 0.934s 2,380K...
Open Graph Description: I spent some time running the argparse bm_subparsers benchmark from pyperformance (1000 optional arguments, 10 iterations) Version Time Function Calls 3.10 0.585s 560K 3.11 0.207s 560K 3.12 0.229s ...
X Description: I spent some time running the argparse bm_subparsers benchmark from pyperformance (1000 optional arguments, 10 iterations) Version Time Function Calls 3.10 0.585s 560K 3.11 0.207s 560K 3.12 0.229s ...
Opengraph URL: https://github.com/python/cpython/issues/142267
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"argparse performance regression in 3.14+ due to colorization overhead","articleBody":"I spent some time running the [argparse `bm_subparsers` benchmark](https://github.com/python/pyperformance/blob/e9fab3a7fc636376dbd150038079cf6039a4ab3f/pyperformance/data-files/benchmarks/bm_argparse/run_benchmark.py#L86) from `pyperformance` (1000 optional arguments, 10 iterations)\n\n| Version | Time | Function Calls |\n|---------|------|----------------|\n| 3.10 | 0.585s | 560K |\n| 3.11 | 0.207s | 560K |\n| 3.12 | 0.229s | 560K |\n| 3.13 | 0.246s | 560K |\n| **3.14** | **0.934s** | **2,380K** |\n| **3.15 (main)** | **0.883s** | **2,367K** |\n\nFor a \"realistic\" CLI with 10 arguments, parser creation is ~3x slower on main compared to 3.13.\n\nThe root cause is that `_get_formatter()` is called twice per `add_argument()` - [once for metavar validation](https://github.com/python/cpython/blob/2dac9e6016c81abbefa4256253ff5c59b29378a7/Lib/argparse.py#L1573) and once in [`_check_help()`](https://github.com/python/cpython/blob/2dac9e6016c81abbefa4256253ff5c59b29378a7/Lib/argparse.py#L1769) for help string validation (called at [the end of `add_argument`](https://github.com/python/cpython/blob/2dac9e6016c81abbefa4256253ff5c59b29378a7/Lib/argparse.py#L1579) ). Each `_get_formatter()` call creates a new `HelpFormatter`, which calls `_set_color()`, which calls `can_colorize()`, which checks 5 environment variables. \n\nI think a viable fix is to cache the `HelpFormatter` on `ArgumentParser` for validation operations. The validation only performs read-only operations (`_format_args`, `_expand_help`) that don't modify formatter state. This preserves the existing `_get_formatter()` behavior while eliminating redundant `_set_color()` calls during argument setup.\n\n\n\u003c!-- gh-linked-prs --\u003e\n### Linked PRs\n* gh-142268\n* gh-142313\n\u003c!-- /gh-linked-prs --\u003e\n","author":{"url":"https://github.com/savannahostrowski","@type":"Person","name":"savannahostrowski"},"datePublished":"2025-12-04T19:37:48.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":1},"url":"https://github.com/142267/cpython/issues/142267"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:cc404f0f-eacb-68bc-d9cf-dfdbbd6000fb |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | A1DA:169C19:2EE0F9E:3DDE37C:696DB886 |
| html-safe-nonce | a529d8ea4f02498d1ab308ed73fe3599a8444d32f17dd49f3e7acf70397e3ec3 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJBMURBOjE2OUMxOToyRUUwRjlFOjNEREUzN0M6Njk2REI4ODYiLCJ2aXNpdG9yX2lkIjoiODU0Nzk2ODUwNjk3NDI4ODAwNiIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 6779e7018cb61f1f1f45194ded086174015f5dda99bbb821e2294fde3d1d61ff |
| hovercard-subject-tag | issue:3696209734 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/python/cpython/142267/issue_layout |
| twitter:image | https://opengraph.githubassets.com/c3be1604408e91e518ab69697dd8ae4b16de42cb10fb0caaf9f522a85ec595af/python/cpython/issues/142267 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/c3be1604408e91e518ab69697dd8ae4b16de42cb10fb0caaf9f522a85ec595af/python/cpython/issues/142267 |
| og:image:alt | I spent some time running the argparse bm_subparsers benchmark from pyperformance (1000 optional arguments, 10 iterations) Version Time Function Calls 3.10 0.585s 560K 3.11 0.207s 560K 3.12 0.229s ... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | savannahostrowski |
| hostname | github.com |
| expected-hostname | github.com |
| None | 4922b452d03cd8dbce479d866a11bc25b59ef6ee2da23aa9b0ddefa6bd4d0064 |
| turbo-cache-control | no-preview |
| go-import | github.com/python/cpython git https://github.com/python/cpython.git |
| octolytics-dimension-user_id | 1525981 |
| octolytics-dimension-user_login | python |
| octolytics-dimension-repository_id | 81598961 |
| octolytics-dimension-repository_nwo | python/cpython |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 81598961 |
| octolytics-dimension-repository_network_root_nwo | python/cpython |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 7e5ae23c70136152637ceee8d6faceb35596ec46 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width