I started a Tkinter application but I'm with problems with buffering. I searched the solution but didn't find it.
Correlated links:
- Calling python script with subprocess popen and flushing the data
- Python C program subprocess hangs at "for line in iter"
- Python subprocess standard output to a variable
As an exemple, this app has two buttons: Start and Stop.
When I press the button Start, the spammer.py is called as a subprocess and when I press the button Stop the program must be killed.
# spammer.py
import time
counter = 0
while counter < 40:  # This process will last 10 second maximum 
    print("counter = %d" % counter)
    counter += 1
    time.sleep(0.25)  # 4 messages/second
While the PrintNumbers.py is running, I want the spammer's output be storage in a variable inside the Tkinter to be used in realtime. But once I try to read the buffer with myprocess.stdout.readline, it stucks and it doesn't continue until the subprocess finish and as consequence for exemple I cannot click on the Stop button.
I read that the function is waiting for EOF to continue, and I tried to use tokens as shown here, and the function that should continue when it finds a   or a \n, but it did not work.
The Tkinter exemple is bellow. After I click at the Start button, I instantly see the message Started reading stdout, and after 10 seconds it shows a lot of messages, while I wanted to show every message over time.
# PrintNumbers.py
import Tkinter as tk
import subprocess
class App:
    def __init__(self, root):
        self.root = root
        self.myprocess = None
        self.logmessages = []
        self.createButtons()
        self.timedUpdate()
    def createButtons(self):
        self.ButtonsFrame = tk.Frame(self.root, width=600, height=400)
        self.ButtonsFrame.pack()
        self.startbutton = tk.Button(self.ButtonsFrame, text="Start",
                                     command=self.__ClickOnStarButton)
        self.stopbutton = tk.Button(self.ButtonsFrame, text="Stop",
                                    command=self.__ClickOnStopButton)
        self.startbutton.pack()
        self.stopbutton.pack()
        self.startbutton["state"] = "normal"
        self.stopbutton["state"] = "disable"
    def __ClickOnStarButton(self):
        print("Click on Start Button")
        self.startbutton["state"] = "disable"
        self.stopbutton["state"] = "normal"
        self.startProcess()
    def __ClickOnStopButton(self):
        print("Click on Stop Button")
        self.startbutton["state"] = "normal"
        self.stopbutton["state"] = "disable"
        self.killProcess()
    
    def startProcess(self):
        command = "python spammer.py"
        self.myprocess = subprocess.Popen(command, stdout=subprocess.PIPE, bufsize=1)
    def killProcess(self):
        self.myprocess.terminate()
        self.myprocess.wait()
        self.myprocess = None
    def timedUpdate(self):
        if self.myprocess is not None:  # There's a process running
            self.getLogText()  # Will get the info from spammer.py
            self.treatOutput()  # Do whatever we want with the data
        root.after(200, self.timedUpdate)  # Every 0.2 seconds we will update
   
    def getLogText(self):
        if self.myprocess is None:  # There's no process running
            return
        # The problem is here
        print("Started reading stdout")
        for line in iter(self.myprocess.stdout.readline, ''):
            print("    Inside the loop. line = '%s'" % line)
            self.logmessages.append(line)
        print("Finished reading stdout")
        
    def treatOutput(self):
        # Any function that uses the spammer's output
        # it's here just to test
        while len(self.logmessages):
            line = self.logmessage.pop(0)
            line = line.replace("counter = ", "")
            mynumber = int(line)
            if mynumber % 3:
                print(mynumber)
if __name__ == "__main__":
    root = tk.Tk()
    app = App(root)
    root.mainloop()
How can I read the output without getting stuck? I'm still using python 2.7, and I don't know if it's the problem either.
