Title: Errors raised in argparse are colorized when redirecting stderr to a file · Issue #139946 · python/cpython · GitHub
Open Graph Title: Errors raised in argparse are colorized when redirecting stderr to a file · Issue #139946 · python/cpython
X Title: Errors raised in argparse are colorized when redirecting stderr to a file · Issue #139946 · python/cpython
Description: Bug report Bug description: (Some) Errors raised in argparse will be colorized when redirecting stderr to a file. Requirements: Errors redirected to a file are not colorized Unittest added to cover the case of error and redirecting of st...
Open Graph Description: Bug report Bug description: (Some) Errors raised in argparse will be colorized when redirecting stderr to a file. Requirements: Errors redirected to a file are not colorized Unittest added to cover...
X Description: Bug report Bug description: (Some) Errors raised in argparse will be colorized when redirecting stderr to a file. Requirements: Errors redirected to a file are not colorized Unittest added to cover...
Opengraph URL: https://github.com/python/cpython/issues/139946
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Errors raised in argparse are colorized when redirecting stderr to a file","articleBody":"# Bug report\n\n### Bug description:\n\n(Some) Errors raised in argparse will be colorized when redirecting stderr to a file. \n\nRequirements:\n\n1. Errors redirected to a file are not colorized\n2. Unittest added to cover the case of error and redirecting of stderr\n\nThe most minimal example can be taken from `calendar` from the stdlib. \n\nWorks as expected with the color displayed correctly.\n\n```bash\n./python.exe -m calendar 2020 01 01\n```\n\nRedirecting stderr\n\n```bash\n./python.exe -m calendar 2020 01 01 2\u003e err\ncat -v err\n^[[1;34musage: ^[[0m^[[1;35mpython.exe -m calendar^[[0m [^[[32m-h^[[0m] [^[[32m-w ^[[33mWIDTH^[[0m] [^[[32m-l ^[[33mLINES^[[0m] [^[[32m-s ^[[33mSPACING^[[0m] [^[[32m-m ^[[33mMONTHS^[[0m] [^[[32m-c ^[[33mCSS^[[0m] [^[[32m-L ^[[33mLOCALE^[[0m] [^[[32m-e ^[[33mENCODING^[[0m] [^[[32m-t ^[[33m{text,html}^[[0m] [^[[32m-f ^[[33mFIRST_WEEKDAY^[[0m] ^[[32m[year]^[[0m ^[[32m[month]^[[0m\npython.exe -m calendar: error: unrecognized arguments: 01\n```\n\nRedirecting stdout will trigger the \"correct\" behavior\n\n```bash\n./python.exe -m calendar 2020 01 01 \u003eout 2\u003e err\n(zatters-314) mkocher@zudio cpython % cat -v err\nusage: python.exe -m calendar [-h] [-w WIDTH] [-l LINES] [-s SPACING]\n [-m MONTHS] [-c CSS] [-L LOCALE] [-e ENCODING]\n [-t {text,html}] [-f FIRST_WEEKDAY]\n [year] [month]\npython.exe -m calendar: error: unrecognized arguments: 01\n```\n\nObservations\n\n\n1. Calling `can_colorize(file=None)` assumes that the stdout is used when `file=None` This implicit use of `can_colorize()` makes the code hard to reason about. \n1. Calling `_set_color` always assumes stdout. \n1. Calling `self.print_usage(_sys.stderr)` is breaking the assumption that stdout is being used. \n1. global ENV var design choice make data flow in the code confusing to debug. Depending on how your argparse code is written and the pattern/style of raising errors, some errors raised are being colorized properly by traceback layer. For example, using `parser.error(...)` or `raise ArgumentTypeError(...)` vs a `raise ValueError()` within your application code.\n1. I think users are going to be a bit confused when setting `ArgumentParser(color=False)` and the error (might) still be colorized (because of the traceback layer determining if it should be colorized). It is documented that configure for traceback is done via ENV vars, but it's not particular clear how the config of these components overlap. \n1. the specific error is not colorized (`python.exe -m calendar: error: unrecognized arguments: 01`) but the usage is? \n\n\nStand alone example for debugging:\n\n```python\nimport sys\nfrom argparse import ArgumentParser, ArgumentTypeError\n\n\ndef validate_lower(sx: str) -\u003e str:\n if any(not s.islower() for s in sx):\n # this will be handled from within argparse.\n # redirecting stderr will still have colorized ascii\n raise ArgumentTypeError(f\"{sx} contains a lowercase string\")\n return sx\n\n\ndef get_parser() -\u003e ArgumentParser:\n p = ArgumentParser(description=\"Testing\", color=True)\n f = p.add_argument\n f('-m', '--max-records', type=int, help=\"Max number of records\", required=True)\n f('-n', '--name', type=validate_lower, help=\"User Name\", required=True)\n f('-t', '--trigger-error', action='store_true', help=\"Trigger error\", required=False)\n return p\n\ndef main(argv: list[str]) -\u003e int:\n p = get_parser()\n pa = p.parse_args(argv)\n if pa.trigger_error:\n # will be colorized by traceback, must be configured by ENV vars to disable\n raise ValueError(\"Trigger an error\")\n\n # this is also a common usage to raise an error\n #p.error(\"Error case\")\n print(f\"Completed running {pa}\")\n return 0\n\n\nif __name__ == \"__main__\":\n sys.exit(main(sys.argv[1:]))\n```\n\n### CPython versions tested on:\n\n3.14\n\n### Operating systems tested on:\n\nmacOS\n\n\u003c!-- gh-linked-prs --\u003e\n### Linked PRs\n* gh-140495\n* gh-140695\n* gh-142398\n\u003c!-- /gh-linked-prs --\u003e\n","author":{"url":"https://github.com/mpkocher","@type":"Person","name":"mpkocher"},"datePublished":"2025-10-11T09:16:19.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":3},"url":"https://github.com/139946/cpython/issues/139946"}
| 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:a21789e9-4b27-c211-6c4d-cef624851ba4 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | E0EA:37FB75:92481B6:C1E2C0B:696E0CC4 |
| html-safe-nonce | 817ba5a9a83c7501e9748e97b03424c83afafba2a26e171289f2c17841436a8e |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFMEVBOjM3RkI3NTo5MjQ4MUI2OkMxRTJDMEI6Njk2RTBDQzQiLCJ2aXNpdG9yX2lkIjoiNDgwMTE2MjkzOTE2MDQ2NDU4MCIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | e71ba22e105fb91e416ec8461eb46994cd79b03e3ff5c6d75864a73ea524f809 |
| hovercard-subject-tag | issue:3505494037 |
| 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/139946/issue_layout |
| twitter:image | https://opengraph.githubassets.com/ed919e1b2b6ba52062829f8d3c15c15d0ea04d7407585187c20290c17b8857a9/python/cpython/issues/139946 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/ed919e1b2b6ba52062829f8d3c15c15d0ea04d7407585187c20290c17b8857a9/python/cpython/issues/139946 |
| og:image:alt | Bug report Bug description: (Some) Errors raised in argparse will be colorized when redirecting stderr to a file. Requirements: Errors redirected to a file are not colorized Unittest added to cover... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | mpkocher |
| hostname | github.com |
| expected-hostname | github.com |
| None | 0b1760aa20e1a810eba6245d04e3885be7363dfe08d08b61f605c852359472e0 |
| 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 | 84090305cd10c2b140bf307f69f57f0892b4f215 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width