Skip to content

gh-153967: handle invalid file object in argparse._print_message - #153969

Open
ptim0626 wants to merge 14 commits into
python:mainfrom
ptim0626:argparse-invalid-file-error
Open

gh-153967: handle invalid file object in argparse._print_message#153969
ptim0626 wants to merge 14 commits into
python:mainfrom
ptim0626:argparse-invalid-file-error

Conversation

@ptim0626

@ptim0626 ptim0626 commented Jul 18, 2026

Copy link
Copy Markdown

The fix for the above issue, which raises a ValueError if an invalid file is explicitly passed to argparse.print_usage and argparse.print_help. Tests added.

@bedevere-app

bedevere-app Bot commented Jul 18, 2026

Copy link
Copy Markdown

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

@python-cla-bot

python-cla-bot Bot commented Jul 18, 2026

Copy link
Copy Markdown

All commit authors signed the Contributor License Agreement.

CLA signed

Comment thread Lib/test/test_argparse.py
Comment thread Lib/test/test_argparse.py Outdated
Comment thread Lib/argparse.py Outdated
@ZeroIntensity

Copy link
Copy Markdown
Member

This is also a user-facing change; please add a news entry.

@bedevere-app

bedevere-app Bot commented Jul 18, 2026

Copy link
Copy Markdown

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

@bedevere-app

bedevere-app Bot commented Jul 18, 2026

Copy link
Copy Markdown

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

@ptim0626

Copy link
Copy Markdown
Author

This is also a user-facing change; please add a news entry.

Thanks, and this was added.

Comment thread Misc/NEWS.d/next/Library/2026-07-18-16-05-38.gh-issue-153967.-OUNXe.rst Outdated
@ptim0626

Copy link
Copy Markdown
Author

Now I have no idea why test_ctypes failed in the CI...

@ZeroIntensity

Copy link
Copy Markdown
Member

That would be #154106. I just updated the branch, which should fix it.

@ptim0626

Copy link
Copy Markdown
Author

The merge fixed the test_ctypes but the sanitizer build failed with test_external_inspection.

@chris-eibl

chris-eibl commented Jul 19, 2026

Copy link
Copy Markdown
Member

No worries. test_external_inspection is a known flaky test. Also the readthedocs hiccuped - I hit "update branch" to trigger CI again and hope for the best :)

Comment thread Lib/argparse.py Outdated
if file is None:
file = _sys.stderr
if file is not None:
file.write(message)

@savannahostrowski savannahostrowski Aug 5, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could we continue to suppress OSError? If writing to sys.stderr raises OSError during ArgumentParser.exit(), the exception escapes before _sys.exit(status) is reached, changing the exception from SystemExit to OSError. We should also add a test for this, probably.

Suggested change
file.write(message)
try:
file.write(message)
except OSError:
pass

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks for catching this so the existing behaviour is kept. I have put a test and made the change accordingly.

One issue of catching OSError inside _print_message is that if, e.g. a non-writable file object, is passed to print_usage/print_help, it will silently fail. The users may benefit from getting a clearer message about what's gone wrong if an error message io.UnsupportedOperation: not writable is emitted (an example of passing a non-writable file). A lot of file-related exceptions are inherited from OSError such as PermissionError etc. Instead of putting the try ... except inside _print_message, could we do

    def exit(self, status=0, message=None):
        if message:
            try:
                self._print_message(message, _sys.stderr)
            except OSError:
                pass
        _sys.exit(status)

This will:

  • ensure argparse.exit still raises SystemExit when sys.stderr raises OSError
  • give clearer exception message when invalid file object (e.g. permission issue, non-writable, wrong file path etc) is passed to print_usage/print_help and not silently failed

Happy to keep the current state if it is more appropriate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

5 participants