pythonmultithreadingpyqt5pyside2jpype

How do I get my Python Qt app to close after using jpype in a QRunnable thread?


I'm using jpype in a QRunnable thread (using PySide2). When I try to close the app, by closing the main window, the Python script doesn't finish. I assume there are still some resources active.

The QThreadPool reports no active threads.

I've created a simple demo app. My real application requires the code in the thread to be run multiple times during its lifetime, so I can't do anything radical like shut down the JVM after the thread runs.

I'd like to know a clean way of tidying up when I want to close down.

import logging
import sys
import PySide2.QtCore as qtc
import PySide2.QtWidgets as qtw
import jpype


class Worker(qtc.QRunnable):
    def run(self):
        jpype.startJVM()
        logging.info("JVM started")


def main():
    logging.basicConfig(level=logging.INFO)

    app = qtw.QApplication(sys.argv)

    window = qtw.QWidget()
    window.show()

    thread_pool = qtc.QThreadPool()
    worker = Worker()

    logging.info("starting thread")
    thread_pool.start(worker)

    app.exec_()

Solution

  • import sys
    import time
    import logging
    import jpype
    import PySide2.QtCore as qtc
    import PySide2.QtWidgets as qtw
    
    
    class Worker(qtc.QRunnable):
        _status = None
    
        def __init__(self):
            super(Worker, self).__init__()
            self.status = -1
    
        @property
        def status(self):
            return self._status
    
        @status.setter
        def status(self, value):
            self._status = value
    
        def run(self):
            logging.info("JVM started")
            jpype.startJVM()
            while True:
                if self.status != -1:
                    # jpype.stopJVM()
                    logging.info("JVM stopped")
                    break
                time.sleep(1)
    
    
    def main():
        logging.basicConfig(level=logging.INFO)
    
        app = qtw.QApplication(sys.argv)
    
        window = qtw.QWidget()
        window.show()
    
        thread_pool = qtc.QThreadPool()
        worker = Worker()
        worker.status = -1
        logging.info("starting thread")
        thread_pool.start(worker)
        status = app.exec_()
        worker.status = status
        sys.exit(status)
    
    
    if __name__ == "__main__":
        main()
    

    output

    INFO:root:starting thread
    INFO:root:JVM started
    INFO:root:JVM stopped