PyQt5 threading communication error
-
Hi everyone,
I would like to ask for your valuable opinion of my stub program, I tried to make it simple and displayed below:class Processing(QObject): def __init__(self): QObject.__init__(self) def match_tracker(self): self.match = Matching(QtCore.QVariant(self.some_list), 3) self.thread = QThread() self.match.moveToThread(self.thread) self.thread.started.connect(self.match.match) self.match.result_signal.connect(self.receive_match_result) self.thread.start() @pygtSlot(str,int) def receive_match_result(self, match_id, track_id): print('{},{}'.format(match_id, track_id)) class Matching(QObject): result_signal = pyqtSignal(str,int) def __init__(self, some_list, id): QObject.__init__(self) self.some_list = some_list self.id = id @pygtSlot() def match(self): print('Matching.match()') # Do processing..... self.result_signal.emit(str_result, int_result)
These are two classes involved in my program. I am able to emit the signal started from Processing class and received in Matching.match(), i.e., I managed to print 'Matching.match()'. However, after the processing operation in Matching.match(), the result_signal should be emitted and received by Processing.receive_match_result(). I cannot print the '{},{}'.format(match_id, track_id) at the first line of the function which means either the signal failed to emit or the slot failed to receive.
How do I check whether a signal is emitted? And do I make any mistake so that I failed to receive the result_signal? Thanks
-
Hi,
I would rather use the
super
keyword to handle heritage. Otherwise the code itself looks fine except that you will create a new Matching object each time you call match_tracker which might be a be overkill. Why not git your Match object two setters, one for each parameter, and then start the thread ? That would avoid re-creatingself.match
each time.As for the signal/slot, as a quick debugging technique, I'd add some more print around the signal emit.
-
@VincentLiu said in PyQt5 threading communication error:
And do I make any mistake so that I failed to receive the result_signal?
From your code as posted (unless there is other code), the signal is emitted, but the slot is no longer around to receive it!
self.thread.start()
starts the thread. But that's at the end of
match_tracker()
. What happens to yourProcessing
object after that is called and the method exits? You need to keep theProcessing
object in existence till the signal is emitted, e.g. some kind of "wait for thread to terminate" or whatever code is suitable for your purposes. Otherwise if you let it go out of scope it gets destroyed, taking the slot/object (receive_match_result()
/self.match
) with it, so the slot never gets hit.Minor:
@pygtSlot()
both occurrences are misspelt: should be@pyqtSlot()
. And (assuming you're PyQt5) somewhere you can Google for says its usage is "deprecated", and you simply shouldn't bother using it any more (I assume it does nothing?).I would rather use the super keyword to handle heritage.
Totally agree! I always write
super().__init__(self)
for inheritors. So how come if this is good does C++ not have equivalent (my beloved C# hasbase
for this)? :) -
@JonB See here for a nice explanation about super.
From the reference guide the pyqtSlot decorator seems to be rather nice to use. I also find that it makes the intent of the code clearer.
-
@SGaist
Forsuper
/base
(lack of) usage in C++, to me it just makes code harder to read & refactor having to explicitly name the base class in each derived function. Also, it may be just me, but when I seeQObject::func()
being used in each derived function to call the base one, my first thought is that it is a call to a static function, which confuses me.For
@pyqtSlot
, I admit I cannot find where I thought it was "deprecated". Perhaps I read https://stackoverflow.com/a/40330912/489865:However, these use-cases are relatively rare, and in most PyQt applications it is not necessary to use pyqtSlot at all. Signals can be connected to any python callable object, whether it is decorated as a slot or not.
The code I am maintaining has hundreds of slot functions and not one
@pyqtSlot
, so perhaps I am used not to encountering it. My apologies for suggesting it was deprecated. -
@jsulm
OOOhhh! My beloved C# allows only single inheritance, so I didn't think of that! I believe Python allows multiple, I haven't looked into whatsuper()
does there, perhaps only allow if single inherited?Also, for C++, from the link @SGaist quoted:
The proposal mentioned the multiple inheritance issue, and would have flagged ambiguous uses.
...
the proposal was implementable, technically sound, and free of major flaws, and handled multiple inheritance.So there's the answer!
-
@JonB https://www.python-course.eu/python3_multiple_inheritance.php
"The question arises how the super functions makes its decision. How does it decide which class has to be used? As we have already mentioned, it uses the so-called method resolution order(MRO)."