Bonjour,
c'est encore moi :p
Contexte:
- - J'ai traduit vers python/Pyqt un exemple en C++ de Bradley T. Hughes à propos de la bonne manière d’utiliser QThread, c'est-à-dire sans subclasser la classe QThread. C'est expliqué dans son blog "You're doing it wrong": http://labs.qt.nokia.com/2010/06/17/...oing-it-wrong/
- - L'exemple en C++ est dans le post "QThread’s no longer abstract": http://labs.qt.nokia.com/2007/07/05/...nger-abstract/
- - Lien direct vers l'exemple: http://chaos.troll.no/~bhughes/producerconsumer2.tar.gz
Résumé:
- - En résumé il s'agit d'un exemple de producteur / consommateur basique. Le producteur produit un certain nombre d'éléments mis dans un QByteArray (cet objet QByteArray est propriété du producteur) et le consommateur prend des éléments de ce tableau.
- - Le producteur passe le QByteArray au consommateur via un signal. Le consommateur agit ensuite sur l'objet QByteArray.
Problème: L'objet reçu par le consommateur (le QByteArray) contient bien les bonnes donnée, mais (c'est là que ce situe le coeur du problème) si l'exemple fonctionne en C++, en python l'objet n'est pas le même, il s'agit d'une copie => résultat, toute action du consommateur sur le QByteArray n'est pas répercutée sur l'objet appartenant au producteur puisque le consommateur reçoit une copie de l'objet et non l'objet lui-même.
Notez que je parle de copie parce que l'id() de l'objet n'est pas le même entre celui du producteur et celui du consommateur. J'ai légèrement changé le code de façon a voir l'id() du QByteArray pour le producteur et le consommateur.
question: comment faire pour recevoir exactement le même objet entre le producteur et le consommateur, sans (a priori) recevoir une copie ?
Output du programme: (notez 'id' ci-dessous qui est différent entre le producteur et le consommateur, alors qu'il "devrait" s'agir du même objet):
In produce. Data Type: <class 'PyQt4.QtCore.QByteArray'> - id: 41177992 - Size: 0
Producer: produced 7890 more bytes, 7890 of 123456 total
In consume. Data Type: <class 'PyQt4.QtCore.QByteArray'> - id: 41178096 - Size: 7890
In Consume: 0
Consumer: consumed 7890 more bytes, 7890 of 123456 total
In produce. Data Type: <class 'PyQt4.QtCore.QByteArray'> - id: 41177992 - Size: 7890
Producer: Consumer failed to consume!
Code python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 import sys from PyQt4 import QtCore from PyQt4.QtCore import pyqtSlot Limit = 123456 BlockSize = 7890 class Producer(QtCore.QObject): produced = QtCore.pyqtSignal(QtCore.QByteArray) finished = QtCore.pyqtSignal() def __init__(self, parent = None): super(Producer, self).__init__(parent) self.bytes = 0 self.data = QtCore.QByteArray() @pyqtSlot() def produce(self): print("In produce. Data Type: {} - id: {} - Size: {}".format(type(self.data), id(self.data), self.data.size())) remaining = Limit - self.bytes if remaining == 0: self.finished.emit() return #this will never happen if self.data.size() != 0: QtCore.qFatal("Producer: Consumer failed to consume!") size = qMin(BlockSize, remaining) self.bytes += size remaining -= size self.data.fill("Q", size) print("Producer: produced {} more bytes, {} of {} total".format(size, self.bytes, Limit)) self.produced.emit(self.data) class Consumer(QtCore.QObject): consumed = QtCore.pyqtSignal() finished = QtCore.pyqtSignal() def __init__(self, parent = None): super(Consumer, self).__init__(parent) self.bytes = 0 @pyqtSlot("QByteArray") def consume(self, data): print("In consume. Data Type: {} - id: {} - Size: {}".format(type(data), id(data), data.size())) if data.size() == 0: QtCore.qFatal("Consumer: Producer failed to produce!") remaining = Limit - self.bytes size = data.size() remaining -= size self.bytes += size data.clear() print("In Consume: ", data.size()) print("Consumer: consumed {} more bytes, {} of {} total".format(size, self.bytes, Limit)) self.consumed.emit() if remaining == 0: self.finished.emit() def qMin(a, b): return a if a < b else b def main(argv): app = QtCore.QCoreApplication(argv) # create the producer and consumer and plug them together producer = Producer() consumer = Consumer() producer.connect(consumer, QtCore.SIGNAL("consumed()"), producer.produce) consumer.connect(producer, QtCore.SIGNAL("produced(QByteArray)"), consumer.consume) # they both got their own threads producerThread = QtCore.QThread() producer.moveToThread(producerThread) consumerThread = QtCore.QThread() consumer.moveToThread(consumerThread) # start producing once the producer's thread has started producer.connect(producerThread, QtCore.SIGNAL("started()"), producer.produce) # when the consumer is done, it stops its thread consumerThread.connect(consumer, QtCore.SIGNAL("finished()"), consumerThread.quit) # when producer thread is done, it quits the application app.connect(producerThread, QtCore.SIGNAL("finished()"), app.quit) # go! producerThread.start() consumerThread.start() app.exec_() if __name__ == '__main__': main(sys.argv)
Merci beaucoup pour votre aide !
Partager