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.

Artemis
  • 2,553
  • 7
  • 21
  • 36

1 Answers1

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()
Pythoscorpion
  • 166
  • 1
  • 10