Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Killing sub process that run inside a thread

I'm using python 3.5.3 with PyQT 5 and I have written GUI with it. This GUI run python code python code with subprocess.run.

In order to leave my GUI active and not frozen during the subprocess operation , i'm running the subprocess in a thread.

In the GUI i have stop button that if the user pressed , I want to terminate the subprocess.

I have no problem to kill the thread by using terminate method of the thread. But that's don't terminate the subprocess.

I've tried to use Popen instead of run but I cant make it to run as subprocess.run does. in addition , I prefer to use the recommended way by Python that's give me also the check_error option

This is how I use subprocess:

class c_run_test_thread(QtCore.QThread):

    def __init__(self,test_file,log_file):
        QtCore.QThread.__init__(self)
        self.test_file = test_file
        self.log_file = log_file

    def __del__(self):
        self.wait()

    def run(self):
        # Thread logic

        try:
            # Run the test with all prints and exceptions go to global log file
            self.test_sub_process = subprocess.run(["python", self.test_file],stdout = self.log_file, stderr = self.log_file,check = True)

    except subprocess.CalledProcessError as error:
        print("Error : {}".format(error))

    # Flush memory to file
    self.log_file.flush(

def stop(self):

    # Flush memory to file
    self.log_file.flush()

And I terminate the thread by

# Stop test thread
self.thread_run_test.terminate()

To sum things up , I want to kill thread while killing its sub process too.

like image 289
Gil.I Avatar asked Nov 23 '25 16:11

Gil.I


1 Answers

There may be other simpler ways to this, but what I did was to

  1. Use subprocess.Popen to run a sub process, instead of subprocess.run, since the latter will not return before the process is terminated
  2. Check if the process is terminated using Popen.poll
  3. Kill the process using Popen.kill

A sample code would be sth. like the following:

self.test_sub_process = subprocess.Popen(["python", self.test_file],
                                         stdout=self.log_file,
                                         stderr=self.log_file)

Wait for termination:

print("Return code: {}".format(self.test_sub_process.wait()))

Or if you want to do something while waiting:

while self.test_sub_process.poll() is None:
    doSomething()
print("Return code: {}".format(self.test_sub_process.poll()))

Then in thread_run_test.terminate(), you can kill the process

self.test_sub_process.kill()

HTH.

like image 98
Joey Zhang Avatar answered Nov 25 '25 04:11

Joey Zhang