Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

PySide2 force killing qapplication



  • Hello

    I have an issue with one "weird" implementation of pyside2.

    the PySide2 is being started inside daemon thread and it shows a window. When user closes the window & starts again the window I get an error that RuntimeError: Please destroy the QApplication singleton before creating a new QApplication instance.

    and running any sort off

        print("Starting app")
        qApp.exec_()
        print("QUitting application")
        qApp.quit()
        qApp.deleteLater()
        del qApp
    

    Does not help at all.

    How can I properly do it ? I know its not the "right way" as Qt should be the main thread but sadly I can't do that here.

    Any hints?

    TIA


  • Lifetime Qt Champion

    Hi,

    Not a direct answer but do you really need to restart the application ? Can't you just show the widget again ?



  • @SGaist If user closes widget then that would finish the qapplication and aventaully delete it ?
    I was thinking of overriding closeEvent to hide() instead but not sure if that will kick...

    Or maybe I'm wrong ?


  • Lifetime Qt Champion

    It depends on what you want your application to do.



  • @SGaist Well the issue starts that when user click second time on widget, it should reload it / show it again... I kinda got it to work with

        try:
            qApp = QApplication(sys.argv)
            widget = mw()
            MainWindow = mainWindow()
            widget.setCentralWidget(MainWindow)
            widget.show()
            print("Starting app")
            qApp.exec_()
        except RuntimeError:
            widget.hide()
            widget.show()
    

    But that won't allow for script to reload so kinda... meh, but kinda works :- )


  • Lifetime Qt Champion

    What exact error do you get ?



  • @SGaist RuntimeError: Please destroy the QApplication singleton before creating a new QApplication instance.



  • @Dariusz
    Try

    app = QApplication.instance()
    if app is None: 
        app = QApplication(sys.argv)
    

    Separately, not sure what your try: ... except ...: is trying to achieve, do you need it, I would remove it as it looks to me like it will just mask errors.



  • @JonB I had that option, but it somehow was erororing. Its as if the thread was not shutting down properly due to Qt keeping it alive. And then when secondary thread kick off try to run the app it was crashing.


  • Lifetime Qt Champion

    Can you provide a minimal example that shows how you are trying to implement that ?



  • @SGaist Hey

    Sure it runs as follows >

    global blndCtx
    global thread
    global qApp
    global widget
    
    #blender operator
    class CustomWindowOperator(Operator):
        bl_idname = 'screen.custom_window'
        bl_label = 'Render Manager'
        mainContextManager = None
    
        #def __init__(self):
        #    super().__init__(mainWrapper)
    
        def execute(self, context):
            print("IM INVOKING pyside2widget!")
            Invoke(context)
            return {'FINISHED'}
    
    def Invoke(context):
        global blndCtx
        global thread
        global qApp
        blndCtx = context
        thread = threading.Thread(target=LoadWindow, name='Daemon')
        thread.daemon = True
        thread.start()
    
    
    def LoadWindow():
        global blndCtx
        global thread
        global qApp
        global widget
        try:
            qApp = QApplication(sys.argv)
            widget = mw()
            MainWindow = mainWindow()
            MainWindow.init(blndCtx, widget)
            widget.setCentralWidget(MainWindow)
            widget.show()
            print("Starting app")
            qApp.exec_()
        except RuntimeError:
            widget.hide()
            widget.show()
        '''
        qApp = QApplication(sys.argv)
        widget = mw()
        MainWindow = mainWindow()
        MainWindow.init(blndCtx, widget)
        widget.setCentralWidget(MainWindow)
        widget.show()
        print("Starting app")
        qApp.exec_()
        qApp.exit()
        qApp.deleteLater()
        del qApp
        '''
    
    

    I used to have what @JonB had suggested but that caused issues. This one "somewhat works". It does not restart the app however like I hoped to, but just shows/hide.

    The globals here are remnent of early tries, where I wanted to test if it exist/force delete etc it. But sadly that did not work.

    TIA



  • @Dariusz
    I'm just going to throw this out there: I do not know whether it might be the cause of problems. ( @SGaist might know whether this relevant?)

    You are keeping global references around, to things like qApp & widget. That is going to stop Python from releasing these objects. Meanwhile, you are seem to be trying to create new QApplication. And you're getting RuntimeError: Please destroy the QApplication singleton before creating a new QApplication instance. I wonder whether the retained references are contributing to/clouding the issue.

    Can you get rid of these globals to start with a cleaner architecture, in case they are getting in the way of proper behaviour?



  • Hey

    I tried getting rid of Globals, sadly did not help.

    Another issue I found is that if I start app again, Ie Try/Else from above and else happens, the app "runs" but I can't make new widgets as I get>QWidget: Cannot create a QWidget without QApplication I wonder how could I re-configure app to have valid qapp application hmhmmm


  • Lifetime Qt Champion

    Would it be possible to have a complete minimal script to test ?



  • @SGaist I'll pull something together. You will need blender 2.83+ however to test it.


Log in to reply