Issue
I have a PySide application that spawns a worker application in a QProcess
. The worker performs a simulation and creates result files to be read by the main application. I want to spawn the worker, give time for it to work, and then check the output. In my test function (I'm using py.test, if that helps), I cannot find a way to wait for the worker without blocking the main thread, thus not allowing the worker process to start and run.
def test_worker_thread():
application = Application() # Waits for and loads result files
application.worker.start() # Runs in a new process
# How to wait right here without blocking thread?
<wait_code>
assert_correct_data(application.worker.results)
For the section called "wait_code", I have tried:
Creating a local object with one attribute called
done
. I connect theworker.finished
signal to settingdone
to True. I then used atime.sleep
loop to block wait for the worker to be done.class WaitObject: def __init__(self): self.condition = False def set_true(self): self.condition = True wait = WaitObject() application.worker.finished(wait.set_true) while not wait.condition: time.sleep(1)
I googled for methods to test asynchronous Qt code, and I came across
QTest.qWait
, which I could use in place oftime.sleep()
without blocking the event loop. However,qWait
is not included in PySide.I have also tried creating a new event loop, like in this thread. However, this seems to block the event loop for
application
, so we cannot finish theworker.start
function and load data while the worker is running.loop = QtCore.QEventLoop() application.worker.finished(loop.quit) loop.exec_()
Any tips?
Solution
It turns out option 3 actually works. My worker wasn't starting because of an unrelated error. Here is some skeleton code in its entirety:
def test_worker_thread():
application = Application() # Waits for and loads result files
application.worker.start() # Runs in a new process
loop = QtGui.QEventLoop()
application.worker.finished(loop.quit) # Resume when worker done
loop.exec_() # Blocks at this line until loop quits
assert_correct_data(application.worker.results)
I am going to work on an abstraction of this pattern. I am going to add a timeout using a singleshot QTimer
that is connected to loop.quit
, in case worker.finished
is never called.
EDIT: Here is a blog post explaining in more detail.
Answered By - John David Reaver
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.