本文介绍了PyQt5 + Python 3:传递列表,字典作为跨线程的信号参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用pyqtSignal将python列表作为参数从工作线程发送到主线程. qt何时创建作为参数传递的对象的副本.根据: http://www .embeddeduse.com/2013/06/29/copied-or-not-copied-arguments-signals-slots/ qt应该复制该对象.但是,在下面的示例中,主线程可以更改从另一个线程发送的列表的内容.

I am using pyqtSignal to send a python list as an argument from worker thread to main thread. When does qt create a copy of the object being passed as argument. According to: http://www.embeddeduse.com/2013/06/29/copied-or-not-copied-arguments-signals-slots/ the qt should make a copy of the object. However, in the example below the main thread can change the contents of the list being sent from another thread.

import sys
import time
from PyQt5.QtCore import QThread, QObject, pyqtSlot, pyqtSignal
from PyQt5.QtWidgets import QApplication

class ClassProcessing(QObject):

    py_sig_send_data = pyqtSignal(list)

    def __init__(self):
        super().__init__()
        # initialize some variables
        self.data = [1, 2, 3, 4, 5]

    def worker(self):
        print(self.data)
        self.py_sig_send_data.emit(self.data)
        time.sleep(1)
        print("modfied data in thread", self.data)

class ClassProcessingThread(QObject):
    def __init__(self):
        super().__init__()
        self.objThread = QThread()
        self.objThread_id = 1
        self.objThread_finished = False
        self.processing = ClassProcessing()
        self.processing.moveToThread(self.objThread)
        self.objThread.started.connect(self.processing.worker)
        self.objThread.start()

class SomeClass(QObject):
    def __init__(self):
        super().__init__()

    @pyqtSlot(list)
    def receive_data(self, data):
        print("received data", data)
        data[1] = 42
        print("modified data", data)

def main():
    app = QApplication(sys.argv)
    processing_thread = ClassProcessingThread()
    some_class = SomeClass()
    processing_thread.processing.py_sig_send_data.
        connect(some_class.receive_data)
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

输出:

[1, 2, 3, 4, 5]
received data [1, 2, 3, 4, 5]
modified data [1, 42, 3, 4, 5]
modified data in thread [1, 42, 3, 4, 5]

有人可以向我解释如何以线程安全的方式在pyqtSignal中传递列表.谢谢.

Can someone please explain to me how to pass a list in a pyqtSignal in a thread-safe manner. Thanks.

推荐答案

在使用信号在线程之间传递容器类型时,PyQt的行为与Qt不同.

PyQt doesn't behave in the same way as Qt when it comes to passing container types between threads using signals.

特别是,没有自动转换[1]到等效的Qt类型,因此没有隐式复制.不过,PyQt确实提供了一种明确请求此类转换的机制.为此,您可以使用QVariantListQVariantMap定义自定义信号:

Specifically, there is no automatic conversion [1] to the equivalent Qt types, and therefore no implicit copying. PyQt does provide a mechanism to explicitly request such conversions, though. To do that, you can define a custom signal using either QVariantList or QVariantMap:

    py_sig_send_data = pyqtSignal('QVariantList')

但是,必须注意QVariantMap仅支持字符串键.

However, it's important to note that QVariantMap only supports string keys.

总而言之,在通过线程之间的信号传递它们之前,显式复制可变的python类型可能更简单,更清晰,更安全.

All in all, though, it's probably simpler, clearer and safer to just explictly copy mutable python types before passing them via signals across threads.

[1]或至少不再.

这篇关于PyQt5 + Python 3:传递列表,字典作为跨线程的信号参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-05 06:51