Running continuous communications using QT and python - python

I used to use TKinter for my GUIS and am now trying to move to QT Designer. I am also new to event based programming. What I am trying to do is listen to communication on my serial port continuously after a start button has been pressed.
I want to call a function update() which takes in the data and manipulates it and writes it to a file. It must then handle any other events queued up before calling update() again. Obviously if I use a while loop my CPU usage goes to 100% and my GUI becomes unresponsive. In TKinter I got around this problem (messily) by using an after_idle call which called update() whenever the GUI was idle.
What is the best practice manner of doing this kind of thing using QT?

Use a thread to monitor the serial port. Use appropriate mechanisms to communicate with the UI (main) thead.
That way you can write your comm module without worrying about the event base nature of the UI. Of course you still cannot use a busy while loop to listen to the serial port. But using the usual read() methods with a time out is ok.
A Queue is well suitable to send data to the UI, and you can write files directly from you comm thread.

Related

Compatibility Between PyPubSub and PyQt

I have been trying to find the most elegant way to decouple my programs from the GUI, such that I can change my front-end without needing to re-write a whole lot of code.
I work with threads a lot, so I often have the need to notify the main GUI thread of asynchronous happenings either through events (for wxPython) or signals (for PyQt). I have experimented a bit with PyPubSub, which may be what I am looking for, but while there are tons of wxPython examples (since it was originally included with it in early development).
I am not aware if there is a 'proper' way to use it with PyQt without running into race conditions. If anyone has some insight on this, I would really appreciate it!
PyPubSub's sendMessage() will call listeners in the same thread as the sender (default Python behavior). In a multithreaded GUI app, you must ensure that listeners that interact with GUI are called in the main thread. Also threads execute independently, so you need each thread to call its own listeners, based on a timed or idle callback mechanism.
The way to call listeners in the correct thread in PyQt is via signals. PyPubSub can still be used in a multithreaded PyQt GUI, but the mechanism used to transfer the "message" from sender to listener would have to be via a signal. There isn't one best way to do it I don't think, depends on details of your app design. You could for example have a QtPubsubHandler that derives from QObject and gets created in main thread, and a QtPubsubSender class that also derives from QObject and gets created in each worker thread. The QtPubSubSender defines a custom signal, say pubsub, which QtPubsubHandler connects to. Then to send a message, the sender does qtPubsubHandler.sendMessage(topic, **data), which causes a pubsub signal to get emitted, which Qt properly queues and eventually signals the QtPubsubHandler, which actually calls pub.sendMessage().
There are many other ways, but you get the general idea: two classes that derive from QObject, and one of them does the actual sending in the same thread as the intended listener, the other uses a signal so everything is thread safe. Actually you don't have to use PyQt signals: but then you would have to have a queue in main thread and have an idle callback that allows it to process any items on the queue.

What is the correct implementation of a mulithreaded python GUI in PyQt4

I'm working on revising an old Java GUI to python and have decided to try to create and implement this in PyQt4.
The original program connects to an outside server and uses the data set by the server to update various figures. These figures are opened from a main GUI and operate and update independently of each other.
I have managed to set something similar up that opens a main GUI window, and connects to an outside server. Where I am having an issue is updating a figure when I get new data from the server (I figured I'd start with one figure then increase from there).
Due to my lack of understanding, or python documentation found, on setting up a client to server connection or threading in the GUI through PyQt I have implemented various work arounds. I connect to the server and read in data via a twisted client. This client is run on a separate thread implemented from the python threading module. This at least from what I can tell works.
I can open up the figures with the newly updated data from the main window but I can not seem to update them from the twisted client thread. I get errors like:
QObject::setParent: Cannot set parent, new parent is in a different thread
or
exceptions.RuntimeError: main thread is not in main loop
From my research I understand that for PyQt windows must be updated from the main thread. I am not sure how to do this. My current implementation has the main thread carrying the main initial window and I am unsure of how to trigger it to update the child windows when new data is received.
Any ideas or links that might give me either an idea how to implement this or what could be a better framework or setup of the GUI?
EDIT: The current set up of my code creates the thread that sets up the client connection and processes the server messages is currently set to a Daemon thread. Since, it does not have an exit condition unless the connection to the server is lost. The Twisted client does not allow the user to return data but since the data I need to update the figures is stored inside of the self variable they are updated during each new data packet. All examples of QTread seem to have an exit condition how would I get it to work without one? Or how do I set up my client side to have an exit statement and then reconnect to get the next message?
Instead of python threads, use QThread and make your own worker class as suggested in the documentation. (2nd example with the WorkerThread).

PyQt : Emtting signal from QThread to QWidget

I've been meaning to implement a chat client/server, with PyQt handling the GUI front. The problem I'm facing is when I want to tell an already connected client that another new client has joined. Initially I worked it around by adding a "refresh users" button which sends the client the updated list. However, now when a client has to message another, I realise that I will obviously have to create a separate thread which keeps on checking for data from the server. I have trying since yesterday, reading various posts/answers, forums but still can't get this to work.
What I want is a separate thread which is executed at the start of the program that checks for data from the server and can emit signals that instigate the function in a GUI thread to change the users list. How do I make a thread that works constantly and emits signals that can be caught by the main GUI loop ? And how should I catch the signal ?
Same as with other Qt components: you create a QThread for your network management, the QThread derived class emits signals with some data coming from network; on the main thread side, you have QObjects and QWidgets that you connect to those signals. Take a look at the following (in that order):
Qt Threading Basics
Thread Support in Qt
How to use QThreads
Another How to use QThreads
what is the correct way to implement a QThread... (example please...)
Once you have read these and tried your own code, then you can post a new question with more specific issues you are having. Otherwise, your question is too broad.

How to create a socket object using multiprocessing and pass it back to the parent process

I wish to create a sock.Socket object from a main program using multiprocessing to avoid blocking the main program if the socket is not available during the creation process.
The socket gets created but can not be returned to the main program.
After some reading it seems that objects can not be shared between python processes. It there a possible design pattern to circumvent this? Is multiprocessing suitable for this application or should I be considering another approach?
You should keep it really simple and have a socket handler thread which:
Opens the Socket,
Retains ownership of it,
Handles it for your main program, i.e. on data arriving passes it to the parent via one of an event, pubsub or a callback,
If the connection is lost either reopens it or lets the parent know and end cleanly,
On shutdown closes the socket for you.
Then everything becomes non-blocking. This is a much cleaner design pattern especially if you use pubsub.

PyQt4 Threading: Sending data back to a thread

I'm writing a program, with a PyQt frontend. To ensure that the UI doesn't freeze up, I use QThreads to emit signals back to the parent. Now, I have reached a point where I need my thread to stop running, emit a signal back to the parent, then wait on the parent to return an approval for the thread to continue (after the user interacts with the UI a little bit).
I've been looking into the QMutex class, along with QThread's wait function.
How should I go about doing this properly?
One approach is using a condition variable.
In my code, however, I prefer using Python's built-in Queue objects to synchronize data between threads. While I'm at it, I use Python's threads as opposed to PyQt threads, mainly because it allows me to reuse the non-GUI part of the code without an actual GUI.

Categories