[ Bug ] print() to stdout with reroute_stdout=True, echo_stdout_stderr=True and reroute_stdout_to_here() hangs PySimpleGUI
wrwetzel opened this issue · comments
Type of Issue (Enhancement, Error, Bug, Question)
Bug
Operating System
Linux Paganini 5.17.3-arch1-1 #1 SMP PREEMPT Thu, 14 Apr 2022 01:18:36 +0000 x86_64 GNU/Linux
PySimpleGUI Port (tkinter, Qt, Wx, Web)
Tkinter
Versions
Python version: 3.10.4 (main, Mar 23 2022, 23:05:40) [GCC 11.2.0]
port: tkinter
tkinter version: 8.6.12
PySimpleGUI version: 4.60.0
PySimpleGUI filename: /usr/lib/python3.10/site-packages/PySimpleGUI/PySimpleGUI.py
Version information can be obtained by calling sg.main_get_debug_data()
Or you can print each version shown in ()
Python version (sg.sys.version
)
PySimpleGUI Version (sg.__version__
)
GUI Version (tkinter (sg.tclversion_detailed
), PySide2, WxPython, Remi)
Your Experience In Months or Years (optional)
55+ years
Years Python programming experience
12+ years
Years Programming experience overall
55+ years
Have used another Python GUI Framework? (tkinter, Qt, etc) (yes/no is fine)
tkinter, Qt
Anything else you think would be helpful?
Troubleshooting
These items may solve your problem. Please check those you've done by changing - [ ] to - [X]
- [x ] Searched main docs for your problem www.PySimpleGUI.org
- Looked for Demo Programs that are similar to your goal Demos.PySimpleGUI.org
- If not tkinter - looked for Demo Programs for specific port
- For non tkinter - Looked at readme for your specific port if not PySimpleGUI (Qt, WX, Remi)
- [x ] Run your program outside of your debugger (from a command line)
- [x ] Searched through Issues (open and closed) to see if already reported Issues.PySimpleGUI.org
- Tried using the PySimpleGUI.py file on GitHub. Your problem may have already been fixed but not released
Detailed Description
Through an error in the structure of my program, which I freely acknowledge is of my own doing, under certain circumstances I called reroute_stdout_to_here() on a Multiline() element when I had already enabled (set True) 'reroute_stdout' and 'echo_stdout_stderr' in the Multiline() options.
Under those conditions a print() causes PySimpleGUI to hang, which can only be resolved by killing the test program process.
If any of those conditions is absent the program works fine, as expected.
I strongly suggest (as this took me over a day to isolate) that PySimpleGui should not hang. Instead it should either post a nastygram or just ignore the condition.
This appears to be a situation that changed between 4.57 and 4.60 as the hang only appeared when I upgraded to 4.60 (at least as best as I can recall).
Code To Duplicate
A short program that isolates and demonstrates the problem (Do not paste your massive program, but instead 10-20 lines that clearly show the problem)
This pre-formatted code block is all set for you to paste in your bit of code:
#!/usr/bin/python
# ----------------------------------------------------------------
# WRW 18 May 2022 - This program demonstrates a rough edge in PySimpleGUI
# arising from a bug of my own where I called reroute_stdout_to_here()
# when also enabling rerouting in the Multiline() options.
# I believe that it should fail gracefully and not hang or even better,
# just ignore the multiple enables.
# It hangs displaying the output from the print() statement and must
# be killed externally.
# Works fine:
# reroute_stdout_to_here() is not called (ReRoute = False)
# or
# Multiline() echo_stdout_stderr = False
# or
# Multiline() reroute_stdout = False
# ----------------------------------------------------------------
import PySimpleGUI as sg
def do_test():
# ----------------------------------------------------------------
build_text = \
sg.Multiline( default_text='',
key='build-text',
write_only = True,
auto_refresh = True,
size=(120, 40),
autoscroll = True,
echo_stdout_stderr = True,
reroute_stdout = True
)
button_close = sg.Button('Close', key='build-button-close' )
build_layout = [ [ build_text ], [button_close] ]
build_window = sg.Window( 'Build Table',
finalize = True,
layout=build_layout,
)
# ----------------------------------------------------------------
ReRoute = True
if ReRoute:
build_window[ 'build-text' ].reroute_stdout_to_here()
for i in range(1, 10):
print( 'hello there' * i )
if ReRoute:
build_window[ 'build-text' ].restore_stdout()
# ----------------------------------------
# Event loop for build window
while True:
event, values = build_window.Read( )
if event == sg.WINDOW_CLOSED:
break
if event == 'build-button-close':
build_window.close()
break
# --------------------------------------------------------------------------
do_test()
Screenshot, Sketch, or Drawing
Watcha Makin?
Birdland is a Linux-based multimedia music viewer and library manager for music books in PDF form including fakebooks. It displays a page of music or a ChordPro song by searching a database of titles and other metadata. Answering the Let's hear how it goes query it also suggests audio files, midi files, JJazzLab songs and YouTube links matching the search.
A secondary feature of Birdland is index management. Birdland contains tools to quickly create indexes using OCR, harmonize indexes from disparate sources, compare them, and integrate them into one database. Birdland ships with index data from 9 sources covering over 100 books and over 20,000 titles. Users can edit existing indexes and add their own.
Options and method of Multiline element
- Option
reroute_stdout
call methodreroute_stdout_to_here
to write to Multiline element. - Option
echo_stdout_stderr
set methodwrite
to append text to Multiline element and also write text to previoussys.stdout
def write(self):
self.update(txt, append=True)
self.previous_stdout.write(txt)
- Method
reroute_stdout_to_here
keep the value ofsys.stdout
inself.previous_stdout
and set it to Multiline element.
def reroute_stdout_to_here(self):
self.previous_stdout = sys.stdout
sys.stdout = self
In your code,
- Set
reroute_stdout=True
will keep Python default stdout<_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>
toself.previous_stdout
, and setstdout
to this Multiline element by call methodreroute_stdout_to_here
first time. So print text to console will be transferred to this Multiline. - text transferred will be append to Multiline element by call method
write
of Multiline element. - Set
echo_stdout_stderr=True
will write text toself.previous_stdout
which is python defaultsys,stdout
now, so text will also print to console. - All above options fine, then you call method
reroute_stdout_to_here
again,self.previous_stdout
will be Multiline element, not the python defaultsys.stdout
. It means PySimpleGUI/tkinter will call methodwrite
which will also call methodwrite
itself recursively. That's why it hangs PySimpleGUI.
Not sure if it clear for you now, you cannot call reroute_stdout_to_here
again after you set reroute_stdout=True
and echo_stdout_stderr=True
.
ReRoute = True
# if ReRoute:
# build_window[ 'build-text' ].reroute_stdout_to_here()
for i in range(1, 10):
print( 'hello there' * i+'\n')
if ReRoute:
build_window[ 'build-text' ].restore_stdout()
Note: There should be a good way to avoid user's wrong call, or need to know much detail about the redirect of stdout
and stderr
.
Too much mixing of parms and methods. Choose one way of doing it. I'm sure I could have done a better job of protecting users from doing sequences that cause problems. There is error checking in PySimpleGUI, it just doesn't cover 100% of the cases... maybe 70% are detected and reported.
Perhaps not enough info in the Cookbook, Demo Programs, Call Reference, etc to explain the Design Patterns that are suggested and safe. The way I develop is to demonstrate good paths assuming others will follow.
Jason, as always, thanks very much for your quick response and detailed explanation of the cause of the hang. I suspected some sort of recursion once I isolated the problem. I agree with your comment on error checking - there is just so much that sensibly possible. But I strongly suggest that there should be a comment in the Call Reference for reroute options AND the reroute_*_to_hear() methods warning to use only one and the consequences of a hang if ignored.
Thanks again,
Bill