Any way to run code before each QThread?

classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

Any way to run code before each QThread?

Ned Batchelder
Hi,

I maintain coverage.py.  I have an issue
(https://github.com/nedbat/coveragepy/issues/582) that the code running
in QThreads aren't measured.  For the stdlib threading module, I have
code that runs as each thread is created to start the measurement.  Is
there any way to do the same for QThreads?

The stdlib feature is threading.settrace
(https://docs.python.org/3/library/threading.html#threading.settrace). I
didn't see anything similar for QThreads, or any other hook that would
give me control before the thread starts running.  Am I overlooking
something?

Does anyone have any other idea about how I could get this working?

Thanks,

--Ned.

_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Any way to run code before each QThread?

David Boddie
On Sun Jul 15 12:30:55 BST 2018, Ned Batchelder wrote:

> I maintain coverage.py.  I have an issue
> (https://github.com/nedbat/coveragepy/issues/582) that the code running
> in QThreads aren't measured.  For the stdlib threading module, I have
> code that runs as each thread is created to start the measurement.  Is
> there any way to do the same for QThreads?

Perhaps. See below.

> The stdlib feature is threading.settrace
> (https://docs.python.org/3/library/threading.html#threading.settrace). I
> didn't see anything similar for QThreads, or any other hook that would
> give me control before the thread starts running.  Am I overlooking
> something?

From the threading.settrace docs:

 "Set a trace function for all threads started from the threading module.
 The func will be passed to sys.settrace() for each thread, before its run()
 method is called."

The QThread.started signal docs (https://doc.qt.io/qt-5/qthread.html#started)
say this:

 "This signal is emitted from the associated thread when it starts executing,
 before the run() function is called."

So it looks like almost exactly what you want. Connect this signal to a slot
(function/method) and perform the same setup there.

At least, it looks simple in principle...

David
_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Any way to run code before each QThread?

Florian Bruhin
On Sun, Jul 15, 2018 at 04:43:41PM +0200, David Boddie wrote:

> On Sun Jul 15 12:30:55 BST 2018, Ned Batchelder wrote:
>
> > I maintain coverage.py.  I have an issue
> > (https://github.com/nedbat/coveragepy/issues/582) that the code running
> > in QThreads aren't measured.  For the stdlib threading module, I have
> > code that runs as each thread is created to start the measurement.  Is
> > there any way to do the same for QThreads?
>
> Perhaps. See below.
>
> > The stdlib feature is threading.settrace
> > (https://docs.python.org/3/library/threading.html#threading.settrace). I
> > didn't see anything similar for QThreads, or any other hook that would
> > give me control before the thread starts running.  Am I overlooking
> > something?
>
> From the threading.settrace docs:
>
>  "Set a trace function for all threads started from the threading module.
>  The func will be passed to sys.settrace() for each thread, before its run()
>  method is called."
>
> The QThread.started signal docs (https://doc.qt.io/qt-5/qthread.html#started)
> say this:
>
>  "This signal is emitted from the associated thread when it starts executing,
>  before the run() function is called."
>
> So it looks like almost exactly what you want. Connect this signal to a slot
> (function/method) and perform the same setup there.
That's only for a given QThread instance though - it'd probably work if
you could somehow find out about all QThread instances created in a
project, but I can't think of a good way to do that.

Florian

--
https://www.qutebrowser.org | [hidden email] (Mail/XMPP)
   GPG: 916E B0C8 FD55 A072 | https://the-compiler.org/pubkey.asc
         I love long mails! | https://email.is-not-s.ms/

_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Any way to run code before each QThread?

Ned Batchelder
On 7/15/18 10:55 AM, Florian Bruhin wrote:

> On Sun, Jul 15, 2018 at 04:43:41PM +0200, David Boddie wrote:
>> On Sun Jul 15 12:30:55 BST 2018, Ned Batchelder wrote:
>>
>>> I maintain coverage.py.  I have an issue
>>> (https://github.com/nedbat/coveragepy/issues/582) that the code running
>>> in QThreads aren't measured.  For the stdlib threading module, I have
>>> code that runs as each thread is created to start the measurement.  Is
>>> there any way to do the same for QThreads?
>> Perhaps. See below.
>>
>>> The stdlib feature is threading.settrace
>>> (https://docs.python.org/3/library/threading.html#threading.settrace). I
>>> didn't see anything similar for QThreads, or any other hook that would
>>> give me control before the thread starts running.  Am I overlooking
>>> something?
>>  From the threading.settrace docs:
>>
>>   "Set a trace function for all threads started from the threading module.
>>   The func will be passed to sys.settrace() for each thread, before its run()
>>   method is called."
>>
>> The QThread.started signal docs (https://doc.qt.io/qt-5/qthread.html#started)
>> say this:
>>
>>   "This signal is emitted from the associated thread when it starts executing,
>>   before the run() function is called."
>>
>> So it looks like almost exactly what you want. Connect this signal to a slot
>> (function/method) and perform the same setup there.
> That's only for a given QThread instance though - it'd probably work if
> you could somehow find out about all QThread instances created in a
> project, but I can't think of a good way to do that.
>
>

I've only poked around for ten minutes, but that's what I'm seeing also:
I could get a signal from a specific thread, but only if I were alerted
to its creation and could connect the signal.

Anyone have any other hacky^H^H^H^H^Hcreative ideas for how to
accomplish this? :)

--Ned.
_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Any way to run code before each QThread?

Phil Thompson-5
On 15 Jul 2018, at 4:24 pm, Ned Batchelder <[hidden email]> wrote:

>
> On 7/15/18 10:55 AM, Florian Bruhin wrote:
>> On Sun, Jul 15, 2018 at 04:43:41PM +0200, David Boddie wrote:
>>> On Sun Jul 15 12:30:55 BST 2018, Ned Batchelder wrote:
>>>
>>>> I maintain coverage.py.  I have an issue
>>>> (https://github.com/nedbat/coveragepy/issues/582) that the code running
>>>> in QThreads aren't measured.  For the stdlib threading module, I have
>>>> code that runs as each thread is created to start the measurement.  Is
>>>> there any way to do the same for QThreads?
>>> Perhaps. See below.
>>>
>>>> The stdlib feature is threading.settrace
>>>> (https://docs.python.org/3/library/threading.html#threading.settrace). I
>>>> didn't see anything similar for QThreads, or any other hook that would
>>>> give me control before the thread starts running.  Am I overlooking
>>>> something?
>>> From the threading.settrace docs:
>>>
>>>  "Set a trace function for all threads started from the threading module.
>>>  The func will be passed to sys.settrace() for each thread, before its run()
>>>  method is called."
>>>
>>> The QThread.started signal docs (https://doc.qt.io/qt-5/qthread.html#started)
>>> say this:
>>>
>>>  "This signal is emitted from the associated thread when it starts executing,
>>>  before the run() function is called."
>>>
>>> So it looks like almost exactly what you want. Connect this signal to a slot
>>> (function/method) and perform the same setup there.
>> That's only for a given QThread instance though - it'd probably work if
>> you could somehow find out about all QThread instances created in a
>> project, but I can't think of a good way to do that.
>>
>>
>
> I've only poked around for ten minutes, but that's what I'm seeing also: I could get a signal from a specific thread, but only if I were alerted to its creation and could connect the signal.
>
> Anyone have any other hacky^H^H^H^H^Hcreative ideas for how to accomplish this? :)

Should I implement QThread.settrace()?

If so can somebody clarify what thread the call to sys.settrace() should be made in? The new thread or the thread from which the new thread is created?

Phil
_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Any way to run code before each QThread?

David Boddie
In reply to this post by Ned Batchelder
On Sunday 15. July 2018 11.24.42 Ned Batchelder wrote:
> On 7/15/18 10:55 AM, Florian Bruhin wrote:

> > That's only for a given QThread instance though - it'd probably work if
> > you could somehow find out about all QThread instances created in a
> > project, but I can't think of a good way to do that.

I missed that detail, though I should have suspected my solution was a bit
too easy.

> I've only poked around for ten minutes, but that's what I'm seeing also:
> I could get a signal from a specific thread, but only if I were alerted
> to its creation and could connect the signal.
>
> Anyone have any other hacky^H^H^H^H^Hcreative ideas for how to
> accomplish this? :)

I think you could install an event filter on the application instance then
handle ThreadChange events. However, this seems to be a recent addition to
Qt. Perhaps in Qt 5.9 or so. I'll post an example shortly.

David
_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Any way to run code before each QThread?

Tobias Rzepka-2
Have a look into the Eric debugger. I've already implemented a solution to intercept the QThread creation and to inject code to trace the excecution.
Tobias

Gesendet von meinem BlackBerry 10-Smartphone.
  Originalnachricht  
Von: David Boddie
Gesendet: Sonntag, 15. Juli 2018 17:54
An: Ned Batchelder
Cc: [hidden email]
Betreff: Re: [PyQt] Any way to run code before each QThread?

On Sunday 15. July 2018 11.24.42 Ned Batchelder wrote:
> On 7/15/18 10:55 AM, Florian Bruhin wrote:

> > That's only for a given QThread instance though - it'd probably work if
> > you could somehow find out about all QThread instances created in a
> > project, but I can't think of a good way to do that.

I missed that detail, though I should have suspected my solution was a bit
too easy.

> I've only poked around for ten minutes, but that's what I'm seeing also:
> I could get a signal from a specific thread, but only if I were alerted
> to its creation and could connect the signal.
>
> Anyone have any other hacky^H^H^H^H^Hcreative ideas for how to
> accomplish this? :)

I think you could install an event filter on the application instance then
handle ThreadChange events. However, this seems to be a recent addition to
Qt. Perhaps in Qt 5.9 or so. I'll post an example shortly.

David
_______________________________________________
PyQt mailing list [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Any way to run code before each QThread?

John Ehresman-2
In reply to this post by Phil Thompson-5
On 7/15/18 11:46 AM, Phil Thompson wrote:
> Should I implement QThread.settrace()?
>
> If so can somebody clarify what thread the call to sys.settrace() should be made in? The new thread or the thread from which the new thread is created?

It would be better to use the callback function that is passed to
threading.settrace than to add QThread.settrace.  It's available as
threading._trace_hook  The sys.settrace function should be called on the
new thread before any Python code on that thread.

The ugly hack that Wing's debugger uses is to wrap to run method of a
QThread instance that sets up the debugger for the thread and then calls
the original run method.

Cheers,

John
_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Any way to run code before each QThread?

Florian Bruhin
In reply to this post by Tobias Rzepka-2
On Sun, Jul 15, 2018 at 05:57:29PM +0200, Tobias Rzepka wrote:
> Have a look into the Eric debugger. I've already implemented a solution to intercept the QThread creation and to inject code to trace the excecution.

That seemes to be here:
http://die-offenbachs.homelinux.org:48888/hg/eric/file/87b1626eb49b/DebugClients/Python/ThreadExtension.py#l361
and just patches the QThread class.

Not sure if that's possible for coverage to do (as it doesn't implement
its own module loading hook, afaik). It definitely gets the
"hacky^H^H^H^H^Hcreative idea" badge, though :D

Florian

--
https://www.qutebrowser.org | [hidden email] (Mail/XMPP)
   GPG: 916E B0C8 FD55 A072 | https://the-compiler.org/pubkey.asc
         I love long mails! | https://email.is-not-s.ms/

_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Any way to run code before each QThread?

Ned Batchelder
In reply to this post by Tobias Rzepka-2
On 7/15/18 11:57 AM, Tobias Rzepka wrote:
> Have a look into the Eric debugger. I've already implemented a solution to intercept the QThread creation and to inject code to trace the excecution.
> Tobias

That sounds great.  Any chance you have a link handy for those of us
unfamiliar with the codebase?

--Ned.

>
> Gesendet von meinem BlackBerry 10-Smartphone.
>    Originalnachricht
> Von: David Boddie
> Gesendet: Sonntag, 15. Juli 2018 17:54
> An: Ned Batchelder
> Cc: [hidden email]
> Betreff: Re: [PyQt] Any way to run code before each QThread?
>
> On Sunday 15. July 2018 11.24.42 Ned Batchelder wrote:
>> On 7/15/18 10:55 AM, Florian Bruhin wrote:
>>> That's only for a given QThread instance though - it'd probably work if
>>> you could somehow find out about all QThread instances created in a
>>> project, but I can't think of a good way to do that.
> I missed that detail, though I should have suspected my solution was a bit
> too easy.
>
>> I've only poked around for ten minutes, but that's what I'm seeing also:
>> I could get a signal from a specific thread, but only if I were alerted
>> to its creation and could connect the signal.
>>
>> Anyone have any other hacky^H^H^H^H^Hcreative ideas for how to
>> accomplish this? :)
> I think you could install an event filter on the application instance then
> handle ThreadChange events. However, this seems to be a recent addition to
> Qt. Perhaps in Qt 5.9 or so. I'll post an example shortly.
>
> David
> _______________________________________________
> PyQt mailing list [hidden email]
> https://www.riverbankcomputing.com/mailman/listinfo/pyqt

_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Any way to run code before each QThread?

David Boddie
In reply to this post by David Boddie
On Sunday 15. July 2018 17.54.07 David Boddie wrote:
>
> I think you could install an event filter on the application instance then
> handle ThreadChange events. However, this seems to be a recent addition to
> Qt. Perhaps in Qt 5.9 or so. I'll post an example shortly.

It looks like ThreadChange events report the _old_ thread an object was in
instead of the new one, so that approach would require some creative ways
to monitor the object in order to determine which thread it ended up in.

It could be made to work but it wouldn't look very nice.

David
_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Any way to run code before each QThread?

Ned Batchelder
In reply to this post by John Ehresman-2
On 7/15/18 12:06 PM, John Ehresman wrote:

> On 7/15/18 11:46 AM, Phil Thompson wrote:
>> Should I implement QThread.settrace()?
>>
>> If so can somebody clarify what thread the call to sys.settrace()
>> should be made in? The new thread or the thread from which the new
>> thread is created?
>
> It would be better to use the callback function that is passed to
> threading.settrace than to add QThread.settrace.  It's available as
> threading._trace_hook  The sys.settrace function should be called on
> the new thread before any Python code on that thread.
>
> The ugly hack that Wing's debugger uses is to wrap to run method of a
> QThread instance that sets up the debugger for the thread and then
> calls the original run method.
How does Wing wrap the run method?  How does it get a chance to do that?

--Ned.
_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Any way to run code before each QThread?

Chris Pezley-2
In reply to this post by Florian Bruhin
You can track all instances of a class in python by creating a cache
which is populated when __new__ is called:

     import weakref
     from PyQt5 import QtCore, QtWidgets


     class MyQThread(QtCore.QThread):
         _instances = weakref.WeakSet()

         def __new__(cls, *args, **kwargs):
             obj = super(MyQThread, cls).__new__(cls, *args, **kwargs)
             cls._instances.add(obj)
             return obj


     def main():
         app = QtWidgets.QApplication([])

         thread_1 = MyQThread()
         thread_2 = MyQThread()
         thread_3 = MyQThread()

         print(list(MyQThread._instances))


     if __name__ == '__main__':
         main()


On 07/15/2018 04:55 PM, Florian Bruhin wrote:

> On Sun, Jul 15, 2018 at 04:43:41PM +0200, David Boddie wrote:
>> On Sun Jul 15 12:30:55 BST 2018, Ned Batchelder wrote:
>>
>>> I maintain coverage.py.  I have an issue
>>> (https://github.com/nedbat/coveragepy/issues/582) that the code running
>>> in QThreads aren't measured.  For the stdlib threading module, I have
>>> code that runs as each thread is created to start the measurement.  Is
>>> there any way to do the same for QThreads?
>> Perhaps. See below.
>>
>>> The stdlib feature is threading.settrace
>>> (https://docs.python.org/3/library/threading.html#threading.settrace). I
>>> didn't see anything similar for QThreads, or any other hook that would
>>> give me control before the thread starts running.  Am I overlooking
>>> something?
>>  From the threading.settrace docs:
>>
>>   "Set a trace function for all threads started from the threading module.
>>   The func will be passed to sys.settrace() for each thread, before its run()
>>   method is called."
>>
>> The QThread.started signal docs (https://doc.qt.io/qt-5/qthread.html#started)
>> say this:
>>
>>   "This signal is emitted from the associated thread when it starts executing,
>>   before the run() function is called."
>>
>> So it looks like almost exactly what you want. Connect this signal to a slot
>> (function/method) and perform the same setup there.
> That's only for a given QThread instance though - it'd probably work if
> you could somehow find out about all QThread instances created in a
> project, but I can't think of a good way to do that.
>
> Florian
>

_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Any way to run code before each QThread?

Florian Bruhin
On Mon, Jul 16, 2018 at 01:52:38PM +0200, Chris Pezley wrote:
> You can track all instances of a class in python by creating a cache which
> is populated when __new__ is called:
>
>     [...]

You need to use your custom MyQThread subclass everywhere for it to work
though - in the case of coverage.py, I'm guessing users don't want their
code to change (and depend on coverage.py) just to measure coverage.

(coverage.py could monkeypatch the QThread class like apparently Eric
and Wing IDE do, but I assume that comes with some nasty gotchas)

Florian

--
https://www.qutebrowser.org | [hidden email] (Mail/XMPP)
   GPG: 916E B0C8 FD55 A072 | https://the-compiler.org/pubkey.asc
         I love long mails! | https://email.is-not-s.ms/

_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Any way to run code before each QThread?

Ned Batchelder
In reply to this post by Florian Bruhin
On 7/15/18 12:06 PM, Florian Bruhin wrote:

> On Sun, Jul 15, 2018 at 05:57:29PM +0200, Tobias Rzepka wrote:
>> Have a look into the Eric debugger. I've already implemented a solution to intercept the QThread creation and to inject code to trace the excecution.
> That seemes to be here:
> http://die-offenbachs.homelinux.org:48888/hg/eric/file/87b1626eb49b/DebugClients/Python/ThreadExtension.py#l361
> and just patches the QThread class.
>
> Not sure if that's possible for coverage to do (as it doesn't implement
> its own module loading hook, afaik). It definitely gets the
> "hacky^H^H^H^H^Hcreative idea" badge, though :D
>

Hmm, coverage.py doesn't (yet) have a module loading hook.  I wonder if
it should?

--Ned.
_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Any way to run code before each QThread?

Chris Pezley-2
In reply to this post by Florian Bruhin
If anyone wants to know what a monkey patch for that would look like
(hacky^H^H^H^H^Hcreative):

     import weakref
     import site
     site._qthread_instances = weakref.WeakSet()

     import PyQt5.QtCore

     @staticmethod
     def __new__(cls, *args, **kwargs):
         obj = super(PyQt5.QtCore.QThread, cls).__new__(cls, *args,
**kwargs)
         site._qthread_instances.add(obj)
         return obj

     PyQt5.QtCore.QThread.__new__ = __new__

You then access the list through site. You just need to make sure that
this loads before the user code, though. I guess since coverage has an
entry-point Ned doesn't need to worry about that.


On 07/16/2018 01:57 PM, Florian Bruhin wrote:

> On Mon, Jul 16, 2018 at 01:52:38PM +0200, Chris Pezley wrote:
>> You can track all instances of a class in python by creating a cache which
>> is populated when __new__ is called:
>>
>>      [...]
> You need to use your custom MyQThread subclass everywhere for it to work
> though - in the case of coverage.py, I'm guessing users don't want their
> code to change (and depend on coverage.py) just to measure coverage.
>
> (coverage.py could monkeypatch the QThread class like apparently Eric
> and Wing IDE do, but I assume that comes with some nasty gotchas)
>
> Florian
>

_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Any way to run code before each QThread?

David Boddie
In reply to this post by Ned Batchelder
Just in case anyone finds it useful or interesting, this is more or less what
I tried to do by applying an event filter to the QApplication object:

class ThreadFilter(QObject):

    report = pyqtSignal(object)
   
    def __init__(self, parent = None):
        QObject.__init__(self, parent)
        self.report.connect(self.collect, Qt.QueuedConnection)
   
    def eventFilter(self, obj, event):
   
        if event.type() == QEvent.ThreadChange:
       
            if not isinstance(obj, QThread):
                print("This thread:", QThread.currentThread())
                print("Object", obj, "in thread:", obj.thread())
                self.report.emit(obj)
       
        return False
   
    def collect(self, obj):
   
        thread = obj.thread()
        print(obj, thread)
        thread.started.connect(self.settrace_start)
        thread.finished.connect(self.settrace_finish)
   
    def settrace_start(self):

        print("Starting thread:", self.sender(), self.sender().isRunning())
   
    def settrace_finish(self):

        print("Finishing thread:", self.sender(), self.sender().isRunning())

The idea is that the filter intercepts the ThreadChange event, which tells us
that an object is being moved between threads, but only tells us about the
old thread. This is handled in the eventFilter method.

However, we have previouly (in the __init__ method) connected a custom signal
(report) to a slot using a QueuedConnection, which means that the signal will
be sent through via an event queue (as I understand it) and not through a
direct call to the slot.

This allows the report signal to be emitted in the eventFilter method but
received after the object has been moved to a new thread (in theory), so that
we can obtain the new thread and connect its signals to other slots to track
its running time.

The event filter can be applied to an QApplication instance, so it can be
applied to QApplication.instance() although this has to occur before the
application creates and runs any new threads, obviously.

    thread_filter = ThreadFilter()
    QApplication.instance().installEventFilter(thread_filter)

Note that this trick only seems to work with recent versions of Qt that
define QEvent::Event::ThreadChange (in C++, QEvent.ThreadChange in PyQt)
and only for applications that use QObject.moveToThread. It doesn't seem to
work for those that subclass QThread and reimplement its run() method.

Hope this inspires someone to build on or improve the concept.

David
_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Any way to run code before each QThread?

John Ehresman-2
In reply to this post by Ned Batchelder
On 7/15/18 8:19 PM, Ned Batchelder wrote:
> How does Wing wrap the run method?  How does it get a chance to do that?

Wing monkeypatches QThread to replace QThread.__init__ with it's own
callable after the QtCore module is loaded.  Within the __init__
replacement, the .run method on the new instance is replaced by a
replacement run callable that calls settrace before calling the saved
run method.  This is done because user code does override the run method
in subclasses of QThread and monkeypatching in __init__ captures the
overridden run method in most cases.  I've attached a snippet of Wing's
code; it's an extract and won't run as is but hopefully it's helpful.

This is an ugly hack and there is code that it won't work for, but it
should work most of the time.

Cheers,

John

_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt

qthreadhack.py (2K) Download Attachment