通过 PyQt signal/slot 连接时,对象被复制的频率是多少?
How often are objects copied when passing across PyQt signal/slot connections?
This interesting article 评估对象在 Qt 中通过 signal/slot 连接时被复制的频率。基本上,结果是当通过 C++ 中的 const 引用传递时,对象要么根本不复制(对于直接连接),要么复制一次(对于排队连接)。
PyQt 怎么样?同样的道理吗?对于Python个对象,做拷贝的时候是不是深拷贝?
我主要对 PyQt5 和 Python 3.
感兴趣
正如@ekhumoro 所建议的那样,我确实进行了尝试,令人惊讶的是,我得到的结果与在 C++ 中进行的测试所揭示的结果不同。基本上,我的测试表明:对象根本没有被复制,即使使用 QueuedConnection
跨线程边界传递也是如此
考虑以下测试代码:
class Object2(QObject):
def __init__(self):
super().__init__()
@pyqtSlot(object)
def slot(self, data):
print("Received data %s in thread %s" % (data, QThread.currentThread()))
while len(data) < 10:
time.sleep(1)
print("Current data is %s" % data)
class Object1(QObject):
def __init__(self):
super().__init__()
sig = pyqtSignal(object)
@pyqtSlot()
def emit_in_thread(self):
self.data = [1]
print("Emitting data %s in thread %s" % (self.data, QThread.currentThread()))
self.sig.emit(self.data)
while len(self.data) < 10:
time.sleep(1)
self.data += [1]
print("Modified data to %s" % self.data)
# App
q_app = QApplication(sys.argv)
# Setup
thread = QThread()
obj1 = Object1()
obj1.moveToThread(thread)
thread.start()
obj2 = Object2()
obj1.sig.connect(obj2.slot, type=Qt.QueuedConnection)
# Emit soon
QTimer.singleShot(200, obj1.emit_in_thread)
# Run event loop
sys.exit(q_app.exec_())
结果是:
Emitting data [1] in thread <PyQt5.QtCore.QThread object at 0x7f037619f948>
Received data [1] in thread <PyQt5.QtCore.QThread object at 0x7f037619faf8>
Current data is [1]
Modified data to [1, 1]
Current data is [1, 1]
Modified data to [1, 1, 1]
Current data is [1, 1, 1]
Modified data to [1, 1, 1, 1]
Current data is [1, 1, 1, 1]
...
这表明尽管发送插槽和接收插槽位于 不同的线程 中,但它们 共享 data
通过 QueuedConnection 发送的对象。
This interesting article 评估对象在 Qt 中通过 signal/slot 连接时被复制的频率。基本上,结果是当通过 C++ 中的 const 引用传递时,对象要么根本不复制(对于直接连接),要么复制一次(对于排队连接)。
PyQt 怎么样?同样的道理吗?对于Python个对象,做拷贝的时候是不是深拷贝?
我主要对 PyQt5 和 Python 3.
感兴趣正如@ekhumoro 所建议的那样,我确实进行了尝试,令人惊讶的是,我得到的结果与在 C++ 中进行的测试所揭示的结果不同。基本上,我的测试表明:对象根本没有被复制,即使使用 QueuedConnection
跨线程边界传递也是如此考虑以下测试代码:
class Object2(QObject):
def __init__(self):
super().__init__()
@pyqtSlot(object)
def slot(self, data):
print("Received data %s in thread %s" % (data, QThread.currentThread()))
while len(data) < 10:
time.sleep(1)
print("Current data is %s" % data)
class Object1(QObject):
def __init__(self):
super().__init__()
sig = pyqtSignal(object)
@pyqtSlot()
def emit_in_thread(self):
self.data = [1]
print("Emitting data %s in thread %s" % (self.data, QThread.currentThread()))
self.sig.emit(self.data)
while len(self.data) < 10:
time.sleep(1)
self.data += [1]
print("Modified data to %s" % self.data)
# App
q_app = QApplication(sys.argv)
# Setup
thread = QThread()
obj1 = Object1()
obj1.moveToThread(thread)
thread.start()
obj2 = Object2()
obj1.sig.connect(obj2.slot, type=Qt.QueuedConnection)
# Emit soon
QTimer.singleShot(200, obj1.emit_in_thread)
# Run event loop
sys.exit(q_app.exec_())
结果是:
Emitting data [1] in thread <PyQt5.QtCore.QThread object at 0x7f037619f948>
Received data [1] in thread <PyQt5.QtCore.QThread object at 0x7f037619faf8>
Current data is [1]
Modified data to [1, 1]
Current data is [1, 1]
Modified data to [1, 1, 1]
Current data is [1, 1, 1]
Modified data to [1, 1, 1, 1]
Current data is [1, 1, 1, 1]
...
这表明尽管发送插槽和接收插槽位于 不同的线程 中,但它们 共享 data
通过 QueuedConnection 发送的对象。