colored-traceback.py
colored-traceback.py copied to clipboard
Windows pyinstaller EXE - `_curses.error: lost sys.stdout`
Attempting to import the library within Windows EXE opened by double clicking, created by pyinstaller, I get the following:
Traceback (most recent call last):
File "tauon/t_modules/t_main.py", line 348, in <module>
File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
File "PyInstaller/loader/pyimod02_importers.py", line 384, in exec_module
File "colored_traceback/always/__init__.py", line 2, in <module>
File "colored_traceback/colored_traceback.py", line 78, in add_hook
File "colored_traceback/colored_traceback.py", line 64, in __init__
File "colored_traceback/colored_traceback.py", line 38, in _determine_formatter
File "colored_traceback/colored_traceback.py", line 34, in _get_term_color_support
_curses.error: lost sys.stdout
Seems to me this function could use a sys.platform check instead?
https://github.com/staticshock/colored-traceback.py/blob/98e6dea7111f7681db823c518f18026374a832b9/colored_traceback/colored_traceback.py#L28-L35
The app in question is Tauon and current commits at the time - https://github.com/Taiko2k/Tauon/commit/c2420e26d2a41941c36a0f3b74a65551afe9f612 - has a prebuilt Windows binary with the issue.
I also previously managed to land on this but no clue how to repro at the moment, so that could just be some pyinstaller issue or an issue on my end:
(t_main.py:351)
Traceback (most recent call last):
File "C:/msys64/home/Yeet/Tauon/.venv/lib/python3.12/site-packages/tauon/t_modules/t_main.py", line 346, in <module>
import colored_traceback.always
File "C:/msys64/home/Yeet/Tauon/.venv/lib/python3.12/site-packages/colored_traceback/always/__init__.py", line 2, in <module>
add_hook(always=True)
File "C:/msys64/home/Yeet/Tauon/.venv/lib/python3.12/site-packages/colored_traceback/colored_traceback.py", line 78, in add_hook
colorizer = Colorizer(style, colors, debug)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:/msys64/home/Yeet/Tauon/.venv/lib/python3.12/site-packages/colored_traceback/colored_traceback.py", line 64, in __init__
self.formatter = _determine_formatter(style, colors, debug)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:/msys64/home/Yeet/Tauon/.venv/lib/python3.12/site-packages/colored_traceback/colored_traceback.py", line 38, in _determine_formatter
colors = colors or _get_term_color_support()
^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:/msys64/home/Yeet/Tauon/.venv/lib/python3.12/site-packages/colored_traceback/colored_traceback.py", line 34, in _get_term_color_support
curses.setupterm()
_curses.error: setupterm: could not find terminfo database
Hm, "lost sys.stdout" sounds vaguely like the stream got closed by whatever process owned it? What interface is even rendering your stdout in that case? Is it something terminal-like, or is it a windows installer output window?
As far as the second error, does this reproduce it: C:/msys64/home/Yeet/Tauon/.venv/Scripts/python.exe -c 'import curses; curses.setupterm()'
What interface is even rendering your stdout in that case?
I have no idea, I just doubleclick the EXE there
As for stdout, it seems to be caused by not checking whether stdout exists before trying to use it.
https://pyinstaller.org/en/stable/common-issues-and-pitfalls.html#sys-stdin-sys-stdout-and-sys-stderr-in-noconsole-windowed-applications-windows-only
Adding a platform check seems bad. I'd rather test for specific functionality, if possible. I see two main issues here that are worth addressing:
- This package uses
stderrthroughout, but curses defaults to probingstdoutunder the hood. That's an unhealthy mismatch, fixable viacurses.setupterm(fd=sys.stderr.fileno()). stdoutas well asstderrare likely auto-closed immediately when you double-click on a PyInstaller file. Here's a reproduction of your error in a sterile environment:
$ python -c 'import sys; sys.stderr.close(); print(sys.stderr.fileno())'
object address : 0x104372800
object refcount : 2
object type : 0x104a49bc8
object type name: ValueError
object repr : ValueError('I/O operation on closed file')
lost sys.stderr
Also reproducible via the test script:
$ python -c 'import sys; sys.stderr.close(); import test'
object address : 0x100b09600
object refcount : 2
object type : 0x100fd9bc8
object type name: ValueError
object repr : ValueError('I/O operation on closed file')
lost sys.stderr
The docs suggest to check if stderr and stdout are available, not to do a platform check:
if sys.stdout is None:
...
if sys.stderr is None:
...
Though it does look like it would be only necessary to check on Windows.
Which docs is this from?
The one I linked in the comment you replied to - https://github.com/staticshock/colored-traceback.py/issues/25#issuecomment-2571591298
Haha, ok, yeah, so I guess the code should check for both a closed stream and a nulled out stream.