GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-148823: Avoid importing `_colorize` when creating an `ArgumentParser` by DavidCEllis · Pull Request #148827 · python/cpython

Conversation

@DavidCEllis

@DavidCEllis DavidCEllis commented Apr 21, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

This is one approach to deferring the _colorize import further.

This makes ._theme and ._decolor into properties so that _colorize is no longer imported when _set_color is called, but only when the theme is accessed.

Currently to prevent the import from subsequently being triggered when a subparser is created, this adds a 'fake' _colorless_theme which just returns empty strings for all attributes which replaces the actual colourless theme from _colorize.

Effectively this is what the colourless theme from _colorize does. I wanted to avoid duplicating all of the attribute names here or further complicating the logic, but there may be a better way to handle this.

Testing this did require an addition to the ensure_lazy_imports test helper to allow running additional code before checking for lazy imports. I think this might also be useful elsewhere when testing imports aren't being triggered earlier than intended.

Command: ./python -c 'import argparse; argparse.ArgumentParser()'

Benchmark 1: main
  Time (mean ± σ):      28.7 ms ±   3.3 ms    [User: 24.1 ms, System: 4.3 ms]
  Range (min … max):    22.2 ms …  46.4 ms    200 runs
 
Benchmark 2: lazy colorize
  Time (mean ± σ):      21.6 ms ±   5.8 ms    [User: 17.3 ms, System: 4.0 ms]
  Range (min … max):    12.1 ms …  36.0 ms    200 runs
 
Summary
  lazy colorize ran
    1.33 ± 0.39 times faster than main

Note that this uses the new lazy imports, this would need significant tweaking if it were to be backported to 3.14.

  • Issue: argparse in 3.14+ is importing _colorize earlier than necessary #148823

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
DavidCEllis added 4 commits April 21, 2026 13:07
@DavidCEllis
Add test helper logic to allow for additional commands in lazy import…
a2c9395
… tests
@DavidCEllis
add tests for lazy imports
629dd53
@DavidCEllis
Lazily import _colorize
4fa408e
This uses a new lazy import so it works with short circuiting alongside a `_colorless_theme` object to prevent the `_colorize` import if color is set to False.

_theme and _decolor are now properties to prevent `_set_color` from performing the imports on creation of a formatter.
@DavidCEllis
subparser has also been fixed
dd8dcf9
@DavidCEllis
DavidCEllis requested review from FFY00, brettcannon, ericsnowcurrently, ncoghlan, savannahostrowski and warsaw as code owners April 21, 2026 13:18
@bedevere-app bedevere-app Bot added the awaiting review label Apr 21, 2026
@bedevere-app bedevere-app Bot mentioned this pull request Apr 21, 2026
argparse in 3.14+ is importing _colorize earlier than necessary #148823
Closed
@DavidCEllis

DavidCEllis commented Apr 21, 2026

Copy link
Copy Markdown
Contributor Author

Ah this pinged more people than I had anticipated.

This appears to be due to the modification to import_helper.py to allow for testing lazy imports with additional logic.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@brettcannon
brettcannon removed their request for review April 27, 2026 21:40
JelleZijlstra
JelleZijlstra reviewed May 6, 2026
View reviewed changes
Comment thread Lib/test/test_argparse.py
self.LAZY_IMPORTS,
)

def test_create_parser(self):

@JelleZijlstra JelleZijlstra May 6, 2026

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth also checking .parse_args()? I think a good outcome is we only import colorize in the uncommon case where there's a parsing error or we invoke --help.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@DavidCEllis DavidCEllis May 6, 2026

Copy link
Copy Markdown
Contributor Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it probably is. I'll add one. I'm fairly sure I at least tried this...

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
hugovk
hugovk reviewed May 6, 2026
View reviewed changes
Comment thread Lib/test/test_argparse.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

DavidCEllis added 2 commits May 6, 2026 15:10
@DavidCEllis
Add a test for parse_args (based on the readme example)
36743f6
@DavidCEllis
remove unnecessary f-string
594619c
@read-the-docs-community

read-the-docs-community Bot commented May 6, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #32570087 | 📁 Comparing c803a10 against main (d206d42)

  🔍 Preview build  

97 files changed · + 2 added · ± 95 modified

+ Added

  • c-api/sentinel.html
  • c-api/slots.html

± Modified

  • glossary.html
  • c-api/concrete.html
  • c-api/exceptions.html
  • c-api/extension-modules.html
  • c-api/index.html
  • c-api/lifecycle.html
  • c-api/module.html
  • c-api/perfmaps.html
  • c-api/stable.html
  • c-api/synchronization.html
  • and 85 more...
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@blurb-it
📜🤖 Added by blurb_it.
45ca6b4
JelleZijlstra
JelleZijlstra reviewed May 6, 2026
View reviewed changes

@JelleZijlstra JelleZijlstra left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This mostly looks good and I'd like to get it into 3.15, but tests are failing, we're actually still importing _colorize in one of the paths.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@DavidCEllis

DavidCEllis commented May 6, 2026

Copy link
Copy Markdown
Contributor Author

Yes, locally on this branch I'm not though which is a little confusing... All of the lazy import tests are now failing. I assume I'll have to handle the merge conflicts to figure out what's going on?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@JelleZijlstra

JelleZijlstra commented May 6, 2026

Copy link
Copy Markdown
Member

Inline comments seem to disappear, but wanted to add that it would be nice to make it so parsing args doesn't trigger the lazy import of shutil. It's apparently only used in the HelpFormatter, which intuitively we shouldn't need if we're not showing help. However, that may be a more involved change than we can get in for 3.15.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@DavidCEllis

DavidCEllis commented May 6, 2026

Copy link
Copy Markdown
Contributor Author

The shutil usage can probably be replaced - it's an environment variable check and then a call to os.get_terminal_size

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@DavidCEllis
Merge remote-tracking branch 'upstream/main' into defer-colorize-argp…
43b1c51
…arse
@JelleZijlstra

JelleZijlstra commented May 6, 2026

Copy link
Copy Markdown
Member

I feel ideally we should avoid instantiating the HelpFormatter at all but haven't looked into how hard that is. Having to inline get_terminal_size() would be a bit unfortunate.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@DavidCEllis

DavidCEllis commented May 6, 2026

Copy link
Copy Markdown
Contributor Author

Ah, it's #149375

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@DavidCEllis

DavidCEllis commented May 6, 2026

Copy link
Copy Markdown
Contributor Author

I generally agree on avoiding the HelpFormatter, there seems to be a lot of logic that gets formatted fairly early though.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

savannahostrowski
savannahostrowski reviewed May 6, 2026
View reviewed changes

@savannahostrowski savannahostrowski left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, this looks great!

The only thing that we may want to consider is that since _colorize is private and _ColorlessTheme exists as an unenforced parallel implementation of ThemeSection.no_colors(), it may be worth adding a small test that imports _colorize, grabs get_theme(force_no_color=True).argparse, iterates its fields, and asserts each is ""?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@DavidCEllis

DavidCEllis commented May 6, 2026

Copy link
Copy Markdown
Contributor Author

Overall, this looks great!

The only thing that we may want to consider is that since _colorize is private and _ColorlessTheme exists as an unenforced parallel implementation of ThemeSection.no_colors(), it may be worth adding a small test that imports _colorize, grabs get_theme(force_no_color=True).argparse, iterates its fields, and asserts each is ""?

That's fine, I can do that.

I'm just trying to work out how to stop the import from being triggered due to the changes from #149375

Right now when any argument is added the help check now calls _apply_text_markup on the help string, importing _colorize due to this change https://github.com/DavidCEllis/cpython/blame/43b1c51105944aea17623e47f45294ba6b571c0c/Lib/argparse.py#L714

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@savannahostrowski

savannahostrowski commented May 6, 2026

Copy link
Copy Markdown
Member

I cannot believe I have to comment via screenshot but inline comments don't work so...
image

I think this should be safe to do since it's read only anyway?

JelleZijlstra, hugovk, s3rius, AlexWaygood, and webknjaz reacted with laugh emoji sergey-miryanov reacted with eyes emoji
All reactions
  • 😄 5 reactions
  • 👀 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@DavidCEllis

DavidCEllis commented May 6, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

Yes! That's what I was looking for. I had got around to turning it off just for _check_help but this is better.

Edit: Now how do I accept a change from a screenshot 😆

savannahostrowski, hugovk, and AlexWaygood reacted with rocket emoji
All reactions
  • 🚀 3 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@savannahostrowski

savannahostrowski commented May 6, 2026

Copy link
Copy Markdown
Member

Edit: Now how do I accept a change from a screenshot 😆

GitHub employees, if you're listening, I have a Copilot feature request.

sethmlarson, Mause, and johnzhou721 reacted with laugh emoji hugovk and AlexWaygood reacted with rocket emoji JacobCoffee reacted with eyes emoji
All reactions
  • 😄 3 reactions
  • 🚀 2 reactions
  • 👀 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

DavidCEllis added 3 commits May 6, 2026 18:03
@DavidCEllis
Don't use colour for validation checks to avoid the _colorize import
0740ca8
@DavidCEllis
Add a test to make sure the fake 'colorless' theme stays in sync with
da033fe
the real one in _colorize
@DavidCEllis
Include the comment from the suggestion
c803a10
savannahostrowski
savannahostrowski approved these changes May 6, 2026
View reviewed changes

@savannahostrowski savannahostrowski left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thank you!

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bedevere-app bedevere-app Bot added awaiting merge and removed awaiting review labels May 6, 2026
@savannahostrowski
Merge branch 'main' into defer-colorize-argparse
1d13627
@savannahostrowski
savannahostrowski enabled auto-merge (squash) May 6, 2026 17:54
@savannahostrowski
savannahostrowski merged commit 8cad740 into python:main May 6, 2026
52 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot removed the awaiting merge label May 6, 2026
@hugovk hugovk mentioned this pull request Jul 29, 2026
Cannot use lazy translation proxies in argparse help #148468
Closed
This was referenced Oct 17, 2026
tests/cli/test_formatter.py fails on Python 3.15: _theme has no setter vcs-python/vcspull#580
Closed
py(3.15): Fix the formatter tests, default to Python 3.15 vcs-python/vcspull#581
Merged
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@JelleZijlstra JelleZijlstra JelleZijlstra left review comments
@hugovk hugovk hugovk left review comments
@savannahostrowski savannahostrowski savannahostrowski approved these changes
@ericsnowcurrently ericsnowcurrently Awaiting requested review from ericsnowcurrently ericsnowcurrently is a code owner
@ncoghlan ncoghlan Awaiting requested review from ncoghlan ncoghlan is a code owner
@warsaw warsaw Awaiting requested review from warsaw warsaw is a code owner
@FFY00 FFY00 Awaiting requested review from FFY00 FFY00 is a code owner

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

4 participants

@DavidCEllis @JelleZijlstra @savannahostrowski @hugovk
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.