-1

I have a Python 2.7 GUI using Tkinter and porting it to 3.7 It pipes a subprocess stdout to a scrolledtext widget and works fine with 2.7 but with 3.7 it is constantly updating the widget and I cannot scroll. Code snippet:

#lauch main
    proc = subprocess.Popen(["python", testPath, filePath] + script_list, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=0)

    #clear the text box widget
    text.delete("1.0", END)

    #check for alternate main.py
    if (alt_main_flag == True):
        text.insert(END, "Using alternate MAIN script in " + filePath + '\n')

    #send the scripts output to the GUI text box
    # for 3.x, had to use bytes() conversion prior to 'in'
    for line in iter(proc.stdout.readline,''):
        if (bytes("Starting ", 'ascii') in line):
            line = line.strip()
            statusvar.set(line)
        else:
            text.insert(END, line)
        if (bytes("end of program", 'ascii') in line):
            statusvar.set("Ready")
        #update in "real time"
        text.see(END)
        root.update()
        text.update_idletasks()

Suggestions?

Mark

MarkB
  • 7
  • 2
  • When I remove the text.see(END) line things are 'better'... I can scroll when the subprocess completes... but of course the text doesn't update/scroll in 'real time'... it stays at the top. Must be a better way! – MarkB Oct 30 '20 at 21:23
  • Noticed when I kill the GUI, python spits this error:File "Z:\Projects\Python_Test_Scripts\Gui_Test\3_8_GUI\GUI_2.py", line 675, in startMain text.update_idletasks() File "C:\Python37\lib\tkinter\__init__.py", line 1182, in update_idletasks self.tk.call('update', 'idletasks') _tkinter.TclError: can't invoke "update" command: application has been destroyed - like the for loop is still running! WHY??? That would explain everything I'm seeing. – MarkB Oct 30 '20 at 22:21
  • That is EXACTLY what's wrong! The for loop never quits. What the hell? – MarkB Oct 30 '20 at 22:37

1 Answers1

0

Found a work-around: added a break to the for loop.

for line in iter(proc.stdout.readline,''):
        if (bytes("Starting ", 'ascii') in line):
            line = line.strip()
            statusvar.set(line)
        else:
            text.insert(END, line)
        if (bytes("end of program", 'ascii') in line):
            statusvar.set("Ready")
        if (len(line) == 0):
            break
            
        #update in "real time"
        text.see(END)
        root.update()
        text.update_idletasks()
MarkB
  • 7
  • 2
  • You can set `text=True` in `subprocess.Popen(...)`, then you don't need to use `bytes(...)`. Also you can simply use `for line in proc.stdout:` instead. And you don't need to call `root.update()`. – acw1668 Oct 31 '20 at 01:18