Python 使用线程回调时解释器崩溃

Python interpreter crashes when using callback from thread

我用 pyqt5 写了一个 Gui-App。

我用threading.Thread创建了一个Thread,它做一些计算。 该线程获取名称、目标、args、kwargs 和一个回调函数,它是我的应用程序 class.

的成员

除最后一次 运行 外,回调有效多次。 例如,100 次呼叫中的前 99 次执行良好,但没有。 100 导致错误。 上次从回调返回后,解释器在大约一秒后崩溃并出现 Windows 事件,事件代码 0xc0000005

回调也有 **kwargs 作为参数

python 本身没有回溯。

任何人都知道可能是什么原因或我做错了什么?

环境:

两个 classes 的最小示例(可能不起作用):

from Controller.filecontroller import Files_Controller as filecontroller

class DialogBatch(QDialog): 
    
    def __init__(self, parent= None):

        #    Initialize super-class
        super(DialogBatch, self).__init__()
        #    Load the GUI Description File, created with QtDesigner
        uic.loadUi('.\GUI_dialog_batch_ui\dialog_batch.ui', self)
        
        #    QProgressBars
        self.progressBar_batch_progress = self.findChild(QProgressBar, 'progressBar_batch_progress')
        
        #    QPushButtons
        self.pushButton_batch_start = self.findChild(QPushButton, 'pushButton_batch_start')
        
        ....  

        #    Filecontroller for file-operations
        self.filecontroller = filecontroller()
        
        #    Thread for executing high-level batch operations; 
        self.__batchthread = None

        #    Show GUI
        self.show()

    ....
    # Callback
    def __update_GUI(self, **kwargs):
        """!    Hidden method for updating the GUI
        @param key-only progress: [int] progress of the task executed
        @return: [int]    1 after finishing
        """
        test = deepcopy(kwargs)
        
        print("Callback entered")

        if "progress" in test:
            self.progressBar_batch_progress.setValue(test["progress"])
            
            print("__update_GUI: Callback called!")
        else:
            print("__update_GUI: No Parameter!")
        print("update GUI finished")
        return 1

    ....
    def slot_pushbutton_start_clicked(self):
        ...
        self.__batchthread = threading.Thread(\
                name='Batchthread', \
                target=self.filecontroller.batch_folder,\
                args=(self.input[0], self.signals[0], self.databases),\
                kwargs={"callback":self.__update_GUI})

        self.__batchthread.start()
        
        ...
class Files_Controller(object):
    ##    Constructor
    # @param self
    def __init__(self):
    ...
        self.__killbatchthread = False
        self._func_callback = None
        ...

    ...
    def batch_folder(self, files, signals, databases, *args, **kwargs):
        
        ...
        self.__params = {}
        files_read = 0
        files_painted = 0
        progress = 0
        
            ...
            for each_file in allfiles:
            ...  
                    ....
                    files_read +=1
                    #    Cancel
                    if self.get_killbatchthreat(): return -1

                    #    Callback for Update
                    if self._func_callback is not None:
                        progress = int((files_read+files_painted)*50/number_of_files)
                        self.__params.clear()
                        self.__params={"progress":progress}
                        self._func_callback(**self.__params)

                    ...

                    files_painted +=1
                    #    Callback for GUI update
                    if self._func_callback is not None:
                        progress = int((files_read+files_painted)*50/number_of_files)
                        self.__params.clear()
                        self.__params={"progress":progress}

                        print("Returnvalue: %i" %(self._func_callback(**self.__params)))
                        for i in range(10):
                            print("Sleeptime: %i" %i)
                            time.sleep(1)

                    ....

最后一次使用最后一个文件调用 _func_callback 时产生了这个输出:

回调输入 __update_GUI: 回调已调用! 更新界面完成 返回值:1 睡眠时间:0 睡眠时间:1

睡眠时间后:1 python 解释器崩溃。

我可以自己解决: 随着设计的改变,问题消失了。

问题是使用来自非 w-gui-thread-function 的回调到 gui class(在 gui 线程中)。 使用信号而不是回调后,它工作正常。

结论: 切勿从 none-gui-thread 函数调用 gui-thread-function。