0

I'm trying to make a graphical interface for another program that simply uses a command line interface. I am attempting to do this by making the command line program output to a tkinter Text widget. I have found several questions about redirecting stdout to a Text widget, however, I have not been able to aply any of them to my problem. Here is a simplified version of my code which presents the same problem:

GUI program:

import threading, subprocess, sys
from tkinter import *


class Out(Text):
    def write(self, text):
        self.insert('end', text)
        self.see('end')

    def fileno(self):return 1


def run():
    sys.stdout = out
    subprocess.run(['test2.py', '10'], stdout=out, shell=True)
    sys.stdout = sys.__stdout__

root = Tk()
out = Out(root)
out.pack()
threading.Thread(target=run).start()
mainloop()

Command line program (testpt2.py in the same directory):

import time, sys

i = int(sys.argv[1])
while i < 100:
    print(i)
    i += 1
    time.sleep(0.1)

The problem with this code is that there is no output, anywhere; all that happens is a tkinter window opens with an empty Text widget. I have tried using a file object in place of the Text widget, and the numbers 10-99 are saved to it. While debugging, I have found that the write method is never actually called, but that I must have a fileno method which returns an integer.


Edit #1: This solution does work for my example code, however in my actual project, I need to pass command line arguments.

Edit #2: I have added a command line argument to demonstrate the above.

Edit #3: I should've said earlier, but I do need the output to happen real-time.

1 Answer 1

1

try this code

import threading
from tkinter import *
from subprocess import Popen, PIPE, run


class Out(Text):
    def write(self, text):
        self.insert('end', text)
        self.see('end')

    def fileno(self):return 1

root = Tk()
out = Out(root)

def run():
    global out
    process = Popen(['python','-u','test2.py','10'], stdin=PIPE, stdout=PIPE, bufsize=1)

    while process.poll() is None:
        out.write(process.stdout.readline())


out.pack()
threading.Thread(target=run).start()
mainloop()
Sign up to request clarification or add additional context in comments.

4 Comments

you can simply replace that (for in range(100)) to while loop so it can handle the contents by any size of data
i replaced readline's logic , i think it's reading output in realtime because each number is coming after 0.1 second
yes it's weird, i'm on windows 10 with python 3.7 installed

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.