0

Hello fellow Overflowers, here's another code I've stuck in. I am using decorator to run some functions asycronously.

file: async.py

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

And then:

import async

[...]

@async.run
def foo():
   while condition:
       do_something()

But now I make a project with QT and those QThreads.

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

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

Which I beleive is ugly and wrong. Could you help me?

2
  • Python threads works perfectly with Qt, did you really need this? Commented Sep 4, 2016 at 18:50
  • @Ceppo93 Some of those threads are working with gui, thus making qt threads preferrable way for seamless experience. Commented Sep 8, 2016 at 7:01

1 Answer 1

2

First here: Threading in a PyQt application: Use Qt threads or Python threads?, for some usufull advise.

A simple "refactoring" of your code, to make it cleaner:

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

EDIT

A simple test:

@run
def test():
    sleep(1)
    print('TEST')


test()
sleep(2)
print('END')
Sign up to request clarification or add additional context in comments.

1 Comment

Ceppo93, you might call it placebo, but I really feel my app is working now more seamlessly with Qthread. Also big thanks for the tip to keep the runner, that was very useful!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.