Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run another process in a loop on a different thread

I am creating a GUI application(wxPython). I need to run another (.exe) application from the GUI application. The subprocess will perform some operation on a user action and return an output to the GUI application

I am running this subprocess in a loop, so that constantly the subprocess is available to execute. What I am doing is, I start a thread(so gui does not freeze) and popen the subprocess in a loop. Not sure if this is the best way.

self.thread = threading.Thread(target=self.run, args=())
self.thread.setDaemon(True)
self.thread.start()

def run(self):
        while self.is_listening:
            cmd = ['application.exe']
            proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
            proc.wait()
            data = ""
            while True:
                txt = proc.stdout.readline()
                    data = txt[5:].strip()
                    txt += data

Now what happens is, if the main application is shutdown, the thread is still waiting for a user action which never came. How can I exit cleanly? The application.exe process can still be seen in the process list, even after GUI app has exited. Any suggestions to improve the whole thing are welcome.

thanks

like image 846
blue01 Avatar asked Nov 05 '22 02:11

blue01


1 Answers

1) Make 'proc' a instance attribute, so you can call it's terminate() or kill() methods before exiting.

self.thread = threading.Thread(target=self.run, args=())
self.thread.setDaemon(True)
self.thread.start()

def run(self):
    while self.is_listening:
        cmd = ['application.exe']
        self.proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        self.proc.wait()
        data = ""
        while True:
            txt = self.proc.stdout.readline()
            data = txt[5:].strip()
            txt += data

2) Use some variable to tell the thread to stop (You will need to use poll() in a loop, instead of using wait()).

self.exit = False
self.thread = threading.Thread(target=self.run, args=())
self.thread.setDaemon(True)
self.thread.start()

def run(self):
    while self.is_listening:
        cmd = ['application.exe']
        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        while proc.poll() is None or not self.exit:
            pass
        data = ""
        while True:
            if self.exit:
                break
            txt = proc.stdout.readline()
            data = txt[5:].strip()
            txt += data

The 'atexit' module documentation can help you with calling things at exit.

like image 122
Artur Gaspar Avatar answered Nov 09 '22 12:11

Artur Gaspar