Hi - I posted this question to Stack Overflow 
(https://stackoverflow.com/questions/68042440/subprocess-not-working-after-onefile-pyinstaller-even-with-stdout-stdin-defined),
 
but haven't had a response, so thought I'd try here.  Apologies if this is 
not the right forum.

I have a tkinter GUI with a text box and run button. Pressing the run 
button turns it to yellow and starts a subroutine that prints a few 
numbers. Text output from the subroutine is redirected to the GUI text box. 
However, after creating a standalone executable file with pyinstaller, it 
no longer works. Pressing the run button doesn't seem to start the 
subprocess. It does turn yellow, but no text appears in the text box and it 
seems to start another instance of the main program - a second GUI appears 
after about 10 seconds which is how long it takes for the initial GUI to 
appear. The run button stays yellow on the initial GUI.

I've seen a bit online about other people having issues with subprocesses 
not running after pyinstaller, but most of the solutions seem to be to make 
sure stdout, stdin are set to subprocess.PIPE which I have, so I'm at a bit 
of a loss what to try next.

When running the resulting executable from Anaconda prompt, I also get no 
error messages or anything useful to help debug.

I'm creating my standalone with this:
pyinstaller --onefile --add-data "testsubprocess.py;." simpleGUI.py

I've also tried without  --add-data "testsubprocess.py;.", making sure my 
executable and testsubprocess.py are in the same folder.

My subprocess file, testsubprocess.py is:
import time

for i in range(3):
    print("%d.%d" % divmod(i, 10))
    time.sleep(0.5)


My main GUI file, simpleGUI.py, is:
import sys
import subprocess
from threading import Thread
import tkinter as tk
from queue import Queue, Empty


def iter_except(function, exception):
    try:
        while True:
            yield function()
    except exception:
        return


class DisplaySubprocessOutputDemo:
    def __init__(self, root):
        self.root = root

        width=600
        height=350
        xloc=0
        yloc=10
        self.root.geometry('%dx%d+%d+%d' % (width, height, xloc, yloc))

        self.statustext = tk.Text(self.root, height=4, width=30)
        self.statustext.grid(row=3, column=1)

        self.startbutton = tk.Button(self.root, text = 'Start', 
command=self.startprocess, bg='green', activebackground = 'orange')
        self.startbutton.config(height = 2, width = 15)
        self.startbutton.grid(row = 5, column=0,sticky='E')
        self.startbuttonpresses = 0
        
        exitbutton = tk.Button(self.root, text = 'Exit', command=self.quit, 
bg='red')
        exitbutton.config(height = 2, width = 15)
        exitbutton.grid(row = 5, column=4, sticky='E')
        
        
    def startprocess(self):    
        self.startbuttonpresses = self.startbuttonpresses+1
        
        if self.startbuttonpresses == 1:
            
            self.startbutton.configure(bg='yellow')
            self.startbutton.configure(text='Stop')
         
            self.process = subprocess.Popen([sys.executable, "-u", 
"testsubprocess.py"], shell=True, stdout=subprocess.PIPE, 
stdin=subprocess.PIPE, stderr=subprocess.STDOUT)
    
            q = Queue(maxsize=1024)  
            t = Thread(target=self.reader_thread, args=[q])
            t.daemon = True 
            t.start()
    
            self.updatetext(q) 
            
        else:
            self.startbuttonpresses = 0
            self.process.kill()
            self.startbutton.configure(bg='green')
            self.startbutton.configure(text='Start')
            

    def reader_thread(self, q):
        try:
            with self.process.stdout as pipe:
                for line in iter(pipe.readline, b''):
                    q.put(line)
        finally:
            q.put(None)


    def updatetext(self, q):
        for line in iter_except(q.get_nowait, Empty): # display all content
            if line is None:
                self.startbuttonpresses = 0
                self.startbutton.configure(bg='green')
                self.startbutton.configure(text='Start')
                
                return
            else:
                self.statustext.insert(tk.END, line)

        self.root.after(400, self.updatetext, q) 


    def quit(self):
        try:
            self.process.kill() 
        except Exception:
            pass
        self.root.destroy()


root = tk.Tk()
app = DisplaySubprocessOutputDemo(root)
root.protocol("WM_DELETE_WINDOW", app.quit)
root.eval('tk::PlaceWindow %s center' % 
root.winfo_pathname(root.winfo_id()))
root.mainloop()

-- 
You received this message because you are subscribed to the Google Groups 
"PyInstaller" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/pyinstaller/127a328b-e2c9-4d08-8a71-f574b0c18420n%40googlegroups.com.

Reply via email to