argparse enables color by default. If an argument is added and there is no tty it will fail like: File "/usr/lib64/python3.14/argparse.py", line 1556, in add_argument formatter = self._get_formatter() File "/usr/lib64/python3.14/argparse.py", line 2725, in _get_formatter formatter = self.formatter_class(prog=self.prog) File "/usr/lib64/python3.14/argparse.py", line 178, in __init__ self._set_color(color) ~~~~~~~~~~~~~~~^^^^^^^ File "/usr/lib64/python3.14/argparse.py", line 198, in _set_color if color and can_colorize(): ~~~~~~~~~~~~^^ File "/usr/lib64/python3.14/_colorize.py", line 314, in can_colorize return os.isatty(file.fileno()) This is seen trying to issue a certificate using freeIPA. IPA uses lib389 which uses argparse for generating command-line options, which is done on import. So merely importing this library within mod_wsgi will cause it to fail because it can't detect that there is no tty available. Reproducible: Always
Reproducer not of the crash but that color=False is not honored. I added an import pdb; pdb.set_trace() to _set_color() in /usr/lib64/python3.14/argparse.py prior to the conditional and color is True. This is the code I used to create the parser and an option import argparse parser = argparse.ArgumentParser(add_help=False, color=False) arg = parser.add_argument('-v', '--verbose', help='verbose', action='store_true', default=False)
For what it's worth this change fixes it for me: diff -u /usr/lib64/python3.14/argparse.py /tmp/argparse.py --- /usr/lib64/python3.14/argparse.py 2025-10-06 20:00:00.000000000 -0400 +++ /tmp/argparse.py 2025-11-13 17:31:11.678000000 -0500 @@ -2722,7 +2722,7 @@ return formatter.format_help() def _get_formatter(self): - formatter = self.formatter_class(prog=self.prog) + formatter = self.formatter_class(prog=self.prog, color=self.color) formatter._set_color(self.color) return formatter
(In reply to Rob Crittenden from comment #0) > argparse enables color by default. > > If an argument is added and there is no tty it will fail like: > > File "/usr/lib64/python3.14/argparse.py", line 1556, in add_argument > formatter = self._get_formatter() > File "/usr/lib64/python3.14/argparse.py", line 2725, in _get_formatter > formatter = self.formatter_class(prog=self.prog) > File "/usr/lib64/python3.14/argparse.py", line 178, in __init__ > self._set_color(color) > ~~~~~~~~~~~~~~~^^^^^^^ > File "/usr/lib64/python3.14/argparse.py", line 198, in _set_color > if color and can_colorize(): > ~~~~~~~~~~~~^^ > File "/usr/lib64/python3.14/_colorize.py", line 314, in can_colorize > return os.isatty(file.fileno()) Is there a part of this traceback missing? What is the exception?
(In reply to Rob Crittenden from comment #1) > Reproducer not of the crash but that color=False is not honored. > > I added an import pdb; pdb.set_trace() to _set_color() in > /usr/lib64/python3.14/argparse.py prior to the conditional and color is True. > > This is the code I used to create the parser and an option > > import argparse > > parser = argparse.ArgumentParser(add_help=False, color=False) > arg = parser.add_argument('-v', '--verbose', help='verbose', > action='store_true', default=False) I don't really understand this code either. When I run it, what do I do next to see the problem?
There's https://github.com/python/cpython/commit/734e15b70dc044f57df4049a22dd769dffdb7d18 which removed the color=self.color argument and replaced it with _set_color(self.color) I still am not entirely sure what exact problem you see. Perhaps it's related to subinterpreters.
Sorry, my paste cut off. The exception raised is: OSError: Apache/mod_wsgi log object is not associated with a file descriptor. In order to see the problem you need to instrument argparse.py to display the value of color in _set_color(). Like this: --- /tmp/argparse.py 2025-11-14 08:46:10.368685441 -0500 +++ /usr/lib64/python3.14/argparse.py 2025-11-14 08:46:43.186354166 -0500 @@ -195,6 +195,8 @@ def _set_color(self, color): from _colorize import can_colorize, decolor, get_theme + print(color) + _sys.exit(1) if color and can_colorize(): self._theme = get_theme(force_color=True).argparse self._decolor = decolor When you run the script you'll get the value of color as True. It should be False as ArgumentParser() was instantiated with color=False. The code shouldn't get as far as determining if a tty is available or not because color should be False. I'm seeing this exception in a PR to the freeipa project. I didn't post any direct links because it is full of other stuff that would just muddy the water.
So what the current argparse code does is this: 1. It initiates a HelpFormatter instance with no explicit color argument 2. The __init__ calls self._set_color(color), which is self._set_color(True) 3. Only then, it sets the color to False and call self._set_color(False) I don't know if this is intentional or not. That said, even when color is True, you probably get: OSError: Apache/mod_wsgi log object is not associated with a file descriptor. Right? So there are two possible fixes here: - the code should probably not call self._set_color(True), self._set_color(False) - The code should handle the OSError and assume it means not a tty Do I get that right?
Either would be fine.
How urgent is this? My upstream fix should be available in Python 3.14.1 scheduled for Tuesday, 2025-12-02.
That is fine. I worked around it by modifying imports to not import the thing that invokes argparse.
FEDORA-2025-e235793f10 (python3.14-3.14.2-1.fc43 and python3-docs-3.14.2-1.fc43) has been submitted as an update to Fedora 43. https://bodhi.fedoraproject.org/updates/FEDORA-2025-e235793f10
FEDORA-2025-e235793f10 (python3.14-3.14.2-1.fc43 and python3-docs-3.14.2-1.fc43) has been pushed to the Fedora 43 stable repository. If problem still persists, please make note of it in this bug report.