0

Anyone who has worked with Multithreaded PyQt4 apps? I was just wondering if the inbuilt signal/slot mechanism coupled with QtThread of PyQt4 framework has any benefit over the standard Python threads (which are designed in my code to handle the UI components in a thread safe way offcourse) using event driven async callback.

I am looking for any major speed or security concerns, any specific run-time exceptions or edge cases. (The UI is quite complex hence a re-write at a later stage would be very counter-productive).

Thanks.

Edit: I realize this might mean replicating some of the already present PyQt core functionality but it is ok if it allows more flexibility within the app.

Deepanshu
  • 9
  • 2
  • 1
    Signals/slots don't use any threads beyond the main thread. Can you explain how you have replaced signals/slots with python threads (which is what your question implies)? Personally I use both threads and signals/slots and they serve very different purposes. Perhaps some more detail of what your app does and/or what your threads are for will help me understand! – three_pineapples Oct 21 '13 at 12:34

2 Answers2

0

There's no point really using Qt/PyQt if your're not using the signal-and-slot mechanism and rolling your own event loop. Basically, you'd be reimplementing the core of the framework itself. But I'm guessing this is not what you're asking about.

It would be nice if you could clarify your question a bit, (because of which I've had to make a few assumptions) but here's the deal:

I think you're a bit confused about what the signal and slot mechanism does. (or maybe not, forgive me for reiterating some stuff that might probably be obvious to you).

The signals-and-slots do not implement threading for you (so the question of using signal/slots having any benefit over standard Python threads is moot)

You're probably assuming that the signal-slot mechanism is multithreaded, and that a slot when called by a signal, executes in a new thread. Well, this is not the case.

The signal and slot mechanism in Qt runs in a single event loop in Qt (implemented by QApplication), which itself runs in a single thread. So signals and slots are not replacements for multi-threading in any way.

If there's a slot that blocks, then it will block your entire application. So any blocking I/O or time intensive functions should ideally be in a separate thread from the UI, and your slots should start execution of these threads. Now whether to use QThread or standard Python threads to implement your own threads is another issue, and it's been asked on StackOverflow before, but I tend to use QThreads for Qt apps.

So if you have a button, and you want to start a file download with the Requests library when its clicked, you'll connect the clicked signal of the QPushButton to a slot say for example downloadButtonClicked, and that slot would start a new QThread which would take care of downloading the file using Requests. You can further connect the finished() signal from the QThread to know when the download is complete and to update your UI

(I'll add a code example if this is indeed what you're asking about. So please clarify your question)

flak37
  • 885
  • 2
  • 10
  • 18
  • Sorry for the ambiguity, I was talking about QtThread Slot/Signal Mechanism vs. callbacks using inbuilt Python Threads. I intend on creating separate threads from UI on event arrival (clicks, etc) and then use callbacks to the main UI thread from the new threads to update the UI (all UI logic in the main thread with locks to keep it thread safe.) I know this might mean replicating some of the already present PyQt functionality but I feel this way I would have a lot more control over my app. (The extra work isn't a concern if it allows more flexibility in the app. Plus it isn't so much of work) – Deepanshu Oct 21 '13 at 13:11
0

Based on your comment to another reply:

Sorry for the ambiguity, I was talking about QtThread Slot/Signal Mechanism vs. callbacks using inbuilt Python Threads. I intend on creating separate threads from UI on event arrival (clicks, etc) and then use callbacks to the main UI thread from the new threads to update the UI (all UI logic in the main thread with locks to keep it thread safe.) I know this might mean replicating some of the already present PyQt functionality but I feel this way I would have a lot more control over my app. (The extra work isn't a concern if it allows more flexibility in the app. Plus it isn't so much of work)

I would say that what you are after is to use QApplication.postEvent() from your threads. With a bit of extra code, you can use this to execute arbitrary methods in the main thread either synchronously or asynchronously.

I'm not sure there are really any advantages or disadvantages to either option (Qt or Python threads). As far as I'm aware, they both still hold the GIL, meaning your program is never truly multithreaded. QThreads come with an event loop, but as you say that isn't hard to write yourself in your own Python thread.

Have you considered using multiple processes instead of multiple threads? While slower to start, you get the advantage of actually having your code run in parallel.

At the end of the day, I think the answer to your question is simply personal preference. Mine would be to avoid using a QThread because it makes it easier to port your application to another widget toolkit in the future if PyQt\PySide\Qt ever die (not that it is very likely, but I've had a bad experience with PyGTK so now I'm wary)

EDIT: Please also look at this, as it has people far better answers than I've given: Threading in a PyQt application: Use Qt threads or Python threads?

Community
  • 1
  • 1
three_pineapples
  • 11,579
  • 5
  • 38
  • 75