On Wed, Jan 22, 2014 at 12:19 AM, Marcus Ottosson <[email protected]>wrote:

> That is some rather naive use of threads you're implying :) but you may
> be right.
>

Well I'm not saying that you are using threads naively. I'm saying that I'm
not aware of there being any validity to your blanket statement that there
are inherently stability issues when passing data through signal/slots with
threads. So if we take the position that the statement isn't true...then it
would imply your might be doing something specific in your usage to produce
instability. Although if there is some concrete evidence that it is a known
issue, then you would be correct :-)


>
> Trying to recreate the issue in a minimal snippet failed, but I'll post it
> here anyway and return once I encounter it again.
>
> Just so I understand you correctly, you've successfully sent data between
> threads, without the use of pyqtSignal or using your own signal
> implementation, and not encountered any issues? That would be delightful,
> as I'm researching how to deal with thread-safety at the moment due to this
> exact issue. But maybe I won't have to!
>

I think maybe I misunderstood you previously. I thought we *were* talking
about using signals to pass data between threads? But you are asking if I
have done it without signals?

Either way, I have done a mixture of all of them without a general problem.

   - Qt Signals emitted with data from a thread that is received in a slot
   of the main thread
   - Threads that emit a signal without data, where the receiver then knows
   to go access a more complex data structure for results (instead of having
   received it all over the signal)
   - Threads that communicate over the standard library Queue container,
   containers guarded with mutexes.

So I am not really sure where the issue is, unless there is some specific
instance that produces a crash, similar to ones I had suggested in the
previous post; Passing QObject references that might be invalid which
produce hard crashes, etc.. There would have to be a reason for the crash,
as far as I know, and not just general instability (I would thing).


>
> The issue at hand relates to delegating computations to separate threads
> so as to increase the interactivity for users clicking about in a gui, so
> threads are run as users interact, with data being sent to and from the ui.
>

Ya, I didn't see an either with this code snippet functioning either. Would
be interested to see some that crash though. I am sure there are cases
where it could happen. Qt has a few different built-in approaches to
threading:  The QThread directly, or subclassed. QRunnable + QThreadpool.
QObject subclass that uses moveToThread.


> Thanks for your feedback Justin.
>
> import time
>
>
> from PyQt5.QtWidgets import *
> from PyQt5.QtGui import *
> from PyQt5.QtCore import *
>
>
>
>
> class Window(QWidget):
>     def __init__(self, parent=None):
>         super(Window, self).__init__(parent)
>
>
>         self.__thread = None
>
>
>         self.button = QPushButton('Push me')
>         self.result = QLineEdit()
>         self.result.setObjectName('ResultWidget')
>
>
>         layout = QBoxLayout(QBoxLayout.TopToBottom, self)
>         layout.addWidget(self.button)
>         layout.addWidget(self.result)
>
>
>         self.button.pressed.connect(self.compute_result)
>
>
>     def compute_result(self):
>         if self.__thread:
>             self.__thread.exit()
>             self.__thread = None
>
>
>         class CascadingThread(QThread):
>             done = pyqtSignal(str)  # Emitted when finished
>             # done = Signal()
>             def run(self):
>                 time.sleep(2)  # Pretend it takes quite a while
>                 self.done.emit('Here is the result')
>
>
>         self.__thread = CascadingThread(self)  # Delegate computation to
> another thread
>         self.__thread.done.connect(self.computed_event)
>         self.__thread.start()
>
>
>         self.button.setEnabled(False)
>         self.result.setText('Computing...')
>
>
>     def computed_event(self, result):
>         self.result.setText(result)
>         self.button.setEnabled(True)
>
>
>
>
>
>
>
>
> if __name__ == '__main__':
>     import sys
>
>
>     app = QApplication(sys.argv)
>
>
>     win = Window()
>     win.show()
>
>
>     sys.exit(app.exec_())
>
>
>
>
> On Tuesday, 21 January 2014 09:48:09 UTC, Justin Israel wrote:
>>
>>
>>
>>
>> On Tue, Jan 21, 2014 at 7:53 PM, Marcus Ottosson <[email protected]>wrote:
>>
>>> Hey Justin, thanks for your feedback. :)
>>>
>>>
>>>> Interesting article. I liked the part where you point out that various
>>>> concepts in PyQt/PySide really just stem from the needs in the C++ world,
>>>> but don't always carry the same relevance in python (QString, QVariant,
>>>> ...). C++ had to do a lot more work to add the "dynamic" characteristics it
>>>> provides (introspection and whatnot).
>>>>
>>>>
>>> Glad you liked it. Perhaps I should add the bit about differences
>>> between API version 1 and 2 of QString too; that was a hurdle for me in the
>>> beginning (particularly its use in modelviews) and I'm sure there are more
>>> instances of problems like that throughout PyQt because, like you say, C++
>>> being slightly different.
>>>
>>>
>>>> Although, I did feel it was a bit light around the subject of what the
>>>> pyqtSignal() is, and what (reading *why)* you can't assign a fresh
>>>> instance in your constructor.
>>>>
>>>
>>> The article really is more about the class at the top, than it is about
>>> pyqtSignal, but you're right, I wish I knew more about it than I do. The
>>> docs<http://pyqt.sourceforge.net/Docs/PyQt5/signals_slots.html#defining-new-signals-with-pyqtsignal>aren't
>>>  very in-depth about this and after glancing over the PyQt source
>>> (source\qpy\QtCore\qpycore_pyqtsignal.h) I quickly decided it was over
>>> my head and decided to go for perceived experiences on this one.
>>>
>>>
>>>> Can you expand on where this information comes from? What kind of
>>>> crashes have you experienced, that you attribute them to the use of Signals
>>>> and QThreads/Threads?
>>>>
>>>
>>> Hm, it worries me that you ask. I can safely say that I've had threads
>>> crash with Signal that does work with pyqtSignal when signal is returning
>>> data, but I'm fairly new in regards to threading and my main source of
>>> attributing crashes with data exchange over threads comes from 
>>> here<http://www.paulbridger.com/multithreading_tutorial/> (as
>>> the class contains no thread synchronisation or locking of resources). I
>>> would love to hear about your experiences in this area!
>>>
>>>
>> I guess I would have needed to see a concrete example of one or more
>> cases that cause a crash to know what is really the problem. But I
>> disagreed with the implication that there is inherent instability when
>> communicating data between threads using signals. I know that there are
>> things you can do that can cause crashes, like trying to call QWidget
>> methods from outside the main gui thread. And there are also wrong ways to
>> set things up, where you are emitting a signal from an object in a thread
>> that was actually created in the main thread and not moved. So you would
>> think you are doing it threaded but really not. Or maybe you are
>> communicating an Qt object that ends up getting garbage collected on the
>> python side, causing an invalid pointer on the C++ side when it gets
>> accessed. Again, its all circumstantial so without a concrete example its
>> hard to put value into that statement.
>>
>>
>>> Best,
>>> Marcus
>>>
>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>  On Mon, Jan 20, 2014 at 9:18 PM, Marcus Ottosson 
>>>> <[email protected]>wrote:
>>>>
>>>>>  Couple of months later, I've had a go with multiple inheritance and
>>>>> with injecting signals via a builder method.
>>>>>
>>>>> The builder works rather well and serves the majority of needs, as
>>>>> "subclasses" would instead be monkey-patched and dependency injected to
>>>>> conform to the given interface (i.e. a fixed set of basic signals and
>>>>> functionality).
>>>>>
>>>>> Signals not being inherited or transferable was solved by making my
>>>>> own signal class.
>>>>>
>>>>> If anyone is interested, I expanded on some of the pros and cons of
>>>>> that here:
>>>>> http://www.abstractfactory.io/blog/dynamic-signals-in-pyqt/
>>>>>
>>>>>
>>>>> On 27 October 2013 14:34, Marcus Ottosson <[email protected]> wrote:
>>>>>
>>>>>> Thanks Justin, I'll give that a go.
>>>>>>
>>>>>> I also found some interesting resources on the topic, as well as the
>>>>>> issue of dynamically allocated signals.
>>>>>> http://trevorius.com/scrapbook/python/pyqt-
>>>>>> multiple-inheritance/#respond
>>>>>> http://trevorius.com/scrapbook/python/binding-
>>>>>> singals-dynamically/#respond
>>>>>>
>>>>>>
>>>>>> On 26 October 2013 21:00, Justin Israel <[email protected]> wrote:
>>>>>>
>>>>>>> I think the multiple inheritance route is just fine, to consider
>>>>>>> your abstract class as a mixin. The signal support is not a problem, 
>>>>>>> since
>>>>>>> it will be processed as part of the QObject's metaclass.
>>>>>>> It's not legal to inherit from multiple QObjects, and you would see
>>>>>>> this when you try and call the constructor on both, which means it 
>>>>>>> doesn't
>>>>>>> even really make sense to use a QObject as the base type of your mixin.
>>>>>>>
>>>>>>> class Abstract(QtGui.QWidget):
>>>>>>>     pass
>>>>>>>
>>>>>>> class Imp(QtGui.QLineEdit, Abstract):
>>>>>>>      def __init__(self):
>>>>>>>         QtGui.QLineEdit.__init__(self)
>>>>>>>         # Abstract.__init__(self) # <-- not legal
>>>>>>>         # RuntimeError: You can't initialize an object twice!
>>>>>>>
>>>>>>>
>>>>>>> Just use object or some other non-qt type. And the naming scheme of
>>>>>>> AbstractMixin, to me, indicates that it is to be used as a mixin and
>>>>>>> doesn't have a custom constructor.
>>>>>>>
>>>>>>> But, the addition of your own metaclass to the mixin will result in
>>>>>>> a conflict like this:
>>>>>>>
>>>>>>> TypeError: Error when calling the metaclass bases
>>>>>>>     metaclass conflict: the metaclass of a derived class must be a
>>>>>>> (non-strict) subclass of the metaclasses of all its bases
>>>>>>>
>>>>>>>
>>>>>>> I've actually used this python recipe to support Qt mixins that have
>>>>>>> a metaclass and it worked great:
>>>>>>> http://code.activestate.com/recipes/204197-solving-the-
>>>>>>> metaclass-conflict/
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On Oct 27, 2013, at 2:25 AM, Marcus Ottosson wrote:
>>>>>>>
>>>>>>> This is more of a general programming question, but I figured it
>>>>>>> applies to Qt programming in particular and I keep encountering it 
>>>>>>> without
>>>>>>> finding any nice enough solution.
>>>>>>>
>>>>>>> I usually write an abstract interface for a set of classes and put
>>>>>>> dependencies on the interface rather than their implementations.
>>>>>>>
>>>>>>> When subclassing QWidget however, how can you make an interface for
>>>>>>> subclasses of an already implemented class? Is multiple inheritance a 
>>>>>>> good
>>>>>>> idea in this scenario?
>>>>>>>
>>>>>>> Currently, I'm writing the interface as a subclass of QWidget, is
>>>>>>> this a good way?
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Marcus
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> *Marcus Ottosson*
>>>>>>> [email protected]
>>>>>>>
>>>>>>> --
>>>>>>> You received this message because you are subscribed to the Google
>>>>>>> Groups "Python Programming for Autodesk Maya" group.
>>>>>>> To unsubscribe from this group and stop receiving emails from it,
>>>>>>> send an email to [email protected].
>>>>>>> To view this discussion on the web visit
>>>>>>> https://groups.google.com/d/msgid/python_inside_maya/CAFRtmOBL_
>>>>>>> NwPBZrMhf12FEROVPnBV_8%2B8fAqyZ2OKXqsTabujw%40mail.gmail.com.
>>>>>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>>>>>
>>>>>>>
>>>>>>>  --
>>>>>>> You received this message because you are subscribed to the Google
>>>>>>> Groups "Python Programming for Autodesk Maya" group.
>>>>>>> To unsubscribe from this group and stop receiving emails from it,
>>>>>>> send an email to [email protected].
>>>>>>> To view this discussion on the web visit
>>>>>>> https://groups.google.com/d/msgid/python_inside_maya/
>>>>>>> 78B20000-CC99-4A5F-9059-A287D7B0419E%40gmail.com.
>>>>>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> --
>>>>>> *Marcus Ottosson*
>>>>>> [email protected]
>>>>>>
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> *Marcus Ottosson*
>>>>> [email protected]
>>>>>
>>>>> --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "Python Programming for Autodesk Maya" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>>> an email to [email protected].
>>>>>  To view this discussion on the web visit https://groups.google.com/d/
>>>>> msgid/python_inside_maya/CAFRtmOBssq4RmHN7iVYwrRJHUtUDk
>>>>> hKisqo1n3guUpefL34NVQ%40mail.gmail.com.
>>>>>
>>>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>>>
>>>>
>>>>  --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "Python Programming for Autodesk Maya" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>> an email to [email protected].
>>>>  To view this discussion on the web visit https://groups.google.com/d/
>>>> msgid/python_inside_maya/CAPGFgA23kWOA94QusaoT2Hh8vaqBk
>>>> G3rH%3DyZmYyK8%3DjK_2yjVg%40mail.gmail.com.
>>>>
>>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>>
>>>
>>>
>>>
>>> --
>>> *Marcus Ottosson*
>>> [email protected]
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "Python Programming for Autodesk Maya" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to [email protected].
>>>  To view this discussion on the web visit https://groups.google.com/d/
>>> msgid/python_inside_maya/CAFRtmODi9dCtdZUDc_Bc39ysKZiPPvEy4mBnOEd7%
>>> 2BmF1nxguaQ%40mail.gmail.com.
>>>
>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>
>>
>>  --
> You received this message because you are subscribed to the Google Groups
> "Python Programming for Autodesk Maya" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/python_inside_maya/aafbc954-9049-4a6f-a631-f81cee7b9394%40googlegroups.com
> .
>
> For more options, visit https://groups.google.com/groups/opt_out.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/python_inside_maya/CAPGFgA1FpnyQHDFC%2BmS_8L%3DrQjJ7QTWKiFircebM7ikVJSiMTQ%40mail.gmail.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to