Python threading with PyQt as decorator
<p>Hello fellow Overflowers, here's another code I've stuck in.
I am using decorator to run some functions asycronously.</p>

<p>file: async.py</p>

<pre><code>from threading import Thread
from functools import wraps


def run(func):
    @wraps(func)
    def async_func(*args, **kwargs):
        func_hl = Thread(target=func, args=args, kwargs=kwargs)
        func_hl.daemon = False
        func_hl.start()
        return func_hl

    return async_func
</code></pre>

<p>And then:</p>

<pre><code>import async

[...]

@async.run
def foo():
   while condition:
       do_something()
</code></pre>

<p>But now I make a project with QT and those QThreads.</p>

<p>So,the question is: how should I improve my decorator to be QT-friendly?
My effort so far was like that:</p>

<pre><code>def better_thread(to_wrap):
    class MyThread(QtCore.QThread):
        def run(self, *args, **kwargs):
            _res = to_wrap(*args, **kwargs)
            return _res

    @wraps(to_wrap)
    def async_func(*args, **kwargs):
        def finish():
            pass
        mythread = MyThread()
        mythread.start()
        result = mythread.run(*args, **kwargs)
        return result
    return async_func
</code></pre>

<p>Which I beleive is ugly and wrong. Could you help me?</p>

<p>First here: <a href="http://stackoverflow.com/questions/1595649/threading-in-a-pyqt-application-use-qt-threads-or-python-threads">Threading in a PyQt application: Use Qt threads or Python threads?</a>, for some usufull advise.</p>

<p>A simple "refactoring" of your code, to make it cleaner:</p>

<pre><code>class Runner(QtCore.QThread):

    def __init__(self, target, *args, **kwargs):
        super().__init__()
        self._target = target
        self._args = args
        self._kwargs = kwargs

    def run(self):
        self._target(*self._args, **self._kwargs)

def run(func):
    @wraps(func)
    def async_func(*args, **kwargs):
        runner = Runner(func, *args, **kwargs)
        # Keep the runner somewhere or it will be destroyed
        func.__runner = runner
        runner.start()

    return async_func
</code></pre>

<p><strong>EDIT</strong></p>

<p>A simple test:</p>

<pre><code>@run
def test():
    sleep(1)
    print('TEST')


test()
sleep(2)
print('END')
</code></pre>

python multithreading qt pyqt qthread