Re: [PyQt] Threads with PyQt. Qt's or Python's?
Le 19/1/2009, Giovanni Bajo ra...@develer.com a écrit: This would work on Qt4 as well, but of course it's not ideal as you need a timer to poll the queue. It's much easier to use QThreads and simply post the events (or use the asynchronous signals). Plus, you can now do non-trivial things from the secondary threads (eg: painting with QPainter over a QImage) so it's worth sitting down and analyzing all these possibilities before desiging the code with Qt4. I started to use QThreads, and I have some minor problems. When my app was build on PyGTK, I was using standard python threads, and a serializer to push PyGTK calls from the threads. The serializer queue was periodically read and executed from the main thread. I replaced the python threads by QThread, and removed all serializer calls. This works pretty well (and faster), except for one thing: I can't refresh my progressbar from the thread. Doing this output the following message: QPixmap: It is not safe to use pixmaps outside the GUI thread QPainter: It is not safe to use drawPixmap() outside the GUI thread The documentation says that a QPainter can only paint on QImage, QPrinter and QPicture, but not on QWidget and QPixmap (it seems that painting on QGraphicsItem works fine, as I don't have warnings; can you confirm?). So, how can I refresh my progressbar from my thread? Is there a Qt mecanism I could use? I'm not that familiar with Qt custom events/signals or so... Thanks, -- Frédéric ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Threads with PyQt. Qt's or Python's?
On Tue Feb 3 10:28:26 GMT 2009, Giovanni Bajo wrote: The trick is that a signal/slot connection across a thread is different from a normal one: in a normal connection, slots are called immediately, within the emit() call. Instead, in an asynchronous connection, when the signal is emitted, an event is posted to the main thread (posting events is thread-safe); then the receiving thread's exec loop will process the event and call the correct slot. For those that don't already know about it, there's an example of inter- thread signal-slot communication in the PyQt Wiki: http://www.diotavelli.net/PyQtWiki/Threading,_Signals_and_Slots The Mandelbrot example included with PyQt4 also shows this technique. David ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Threads with PyQt. Qt's or Python's?
Le 3/2/2009, Giovanni Bajo ra...@develer.com a écrit: PS: does it already exist a simple solution to adapt this code: thread = threading.Thread(target=func) thread.start() using QThread? Yes: QtConcurrent::run. :o) Thank you all for your help! -- Frédéric ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Threads with PyQt. Qt's or Python's?
Le 3/2/2009, Giovanni Bajo ra...@develer.com a écrit: The trick is that a signal/slot connection across a thread is different from a normal one: in a normal connection, slots are called immediately, within the emit() call. Instead, in an asynchronous connection, when the signal is emitted, an event is posted to the main thread (posting events is thread-safe); then the receiving thread's exec loop will process the event and call the correct slot. In this last case, does the call to emit() immediatly return, and the thread go on with the next instruction, or does it wait until the event has really called the slot? -- Frédéric ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Threads with PyQt. Qt's or Python's?
A Dimarts 03 Febrer 2009, Frédéric va escriure: PS: does it already exist a simple solution to adapt this code: thread = threading.Thread(target=func) thread.start() using QThread? Not that I know of, but it's trivial to implement. Something like this should do: class FunctionThread(QThread): def __init__(self, function, parent=None): QThread.__init__(self, parent) self.function = function def run(self): self.function() -- Frédéric ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt -- Albert Cervera i Areny http://www.NaN-tic.com ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Threads with PyQt. Qt's or Python's?
On mardi 03 février 2009, Giovanni Bajo wrote: In this last case, does the call to emit() immediatly return, and the thread go on with the next instruction, or does it wait until the event has really called the slot? Depends on the connection type (which you can manually specify during the connect() call, or leave the default). The default (for connections between different threads) is Qt.QueuedConnection, which means that the emit() call exits immediately. Otherwise, you can specify Qt.BlockingQueueConnection: the emitting thread will wait until the receiving thread has found time to process all the slots. Ok (Qt is really powerfull!). Notice that it's easy to deadlock, if you don't pay enough attention (and even if you do ;). Why do you say it is easy to deadlock? Do you mean that Qt can do unexpected things? -- Frédéric http://www.gbiloba.org ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Threads with PyQt. Qt's or Python's?
On 2/3/2009 5:17 PM, Frédéric wrote: On mardi 03 février 2009, Giovanni Bajo wrote: Notice that it's easy to deadlock, if you don't pay enough attention (and even if you do ;). Why do you say it is easy to deadlock? Do you mean that Qt can do unexpected things? No: I meant that a programmer's mistake is easy because you're basically blocking a thread on another one. If for instance you send a similar blocking queued signal from this thread to the former, you get a deadlock (since the former is blocked waiting for the first signal to finish its process). My suggestion mostly is not to use blocking queue signals. -- Giovanni Bajo Develer S.r.l. http://www.develer.com ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Threads with PyQt. Qt's or Python's?
On 2/3/2009 12:24 PM, Frédéric wrote: Le 3/2/2009, Giovanni Bajo ra...@develer.com a écrit: The documentation says that a QPainter can only paint on QImage, QPrinter and QPicture, but not on QWidget and QPixmap (it seems that painting on QGraphicsItem works fine, as I don't have warnings; can you confirm?). I'm unsure but yes, it probably works because it's a simply a QImage under the hoods. Ok. Read the documentation about connecting signals and slots across threads (asynchronous thread connection). What you want is to simply emit a signal from the thread (self.emit(SIGNAL(UPDATED_PROGRESS), value)), and connect to that signal from the main thread; in the slot, update the widget. The trick is that a signal/slot connection across a thread is different from a normal one: in a normal connection, slots are called immediately, within the emit() call. Instead, in an asynchronous connection, when the signal is emitted, an event is posted to the main thread (posting events is thread-safe); then the receiving thread's exec loop will process the event and call the correct slot. Ok, I got it! I'll try to implement this... Thanks again for your help :o) PS: does it already exist a simple solution to adapt this code: thread = threading.Thread(target=func) thread.start() using QThread? Yes: QtConcurrent::run. -- Giovanni Bajo Develer S.r.l. http://www.develer.com ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Threads with PyQt. Qt's or Python's?
On mar, 2009-01-20 at 12:08 +0800, Christoph Burgmer wrote: Am Tuesday, 20. January 2009 schrieb Giovanni Bajo: On 1/19/2009 4:36 PM, Christoph Burgmer wrote: [...] I am doing a QCoreApplication.postEvent() out of run() from a threading.Thread class without any problems. That's only because you are lucky. It's not something that's officially supported and I have spent days debugging random crashes that turned out being Qt accesses from threads allocated by Python. I suggest you to fix your code. We have an unlucky situation here, Qt documents neither say that mixing threading libraries is ok, nor does it say it could lead to clashes. To be more precise, using a different underlying C-level library is not going to fly. The question here is: assuming that Python and Qt ends up calling the same underlying library (eg: pthread on Linux), does it work if I create a thread from Python and then use Qt's calls? Now guessing won't help, but I'll do it anyway: QCoreApplication::postEvent() is thread-safe and thus has the highest safety level one could whish for in the Qt threading system. It works by adding the event to the event queue and returning immediatelly. It's the main event loop that then takes over. Now from that I would assume the only clashes could occur when fiddeling with the event queue. Instead of assuming some magic done in every thread I rather believe that synchronisation is done in the local method, postEvent(). Now things going wrong would mean that synchronisation there does depend on the threads all adhering to the same special protocol, something that IMHO is not needed to complete this task. For your reasoning to be true, QThread's constructor should be an empty function. Instead QThread's constructor initializes a QThreadPrivate object, whose create a QThreadData TLS object, who is in turn vital to the working of, eg., QThread::current(), that postEvent() calls. Moreover, it's not only postEvent() at stake here: you are probably constructing an event object before passing it to postEvent(), so you will have to check that everything also in there is compatible with using a different high-level threading library (included, eg., object construction and ownership transfer at both the sip/pyqt/qt level). -- Giovanni Bajo Develer S.r.l. http://www.develer.com ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Threads with PyQt. Qt's or Python's?
Am Monday, 19. January 2009 schrieb Giovanni Bajo: On 1/19/2009 3:13 PM, eliben wrote: I've seen various references to this issue before, but nothing to fully address it as I'd expect. Can you comment on the pros and cons of using QThread vs Python's threads with PyQt? I'll begin: on the surface, Python's threads make more sense because they're Qt independent and can be ported between apps that don't necessarily depend on Qt (for example a web version of a GUI app). The Python thread API is powerful enough for all uses, it seems. However, there are concerns. Perhaps QThreads are more efficient? Or maybe more tightly integrated with the other parts of PyQt, so it's easier to use them? It's mostly the same. The main difference is that QThreads are better integrated with Qt (asynchrnous signals/slots, event loop, etc.). Also, you can't use Qt from a Python thread (you can't for instance post event to the main thread through QApplication.postEvent): you need a QThread for that to work. I am doing a QCoreApplication.postEvent() out of run() from a threading.Thread class without any problems. Christoph ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Threads with PyQt. Qt's or Python's?
Le 19/1/2009, Christoph Burgmer chri...@gmx.de a écrit: I am doing a QCoreApplication.postEvent() out of run() from a threading.Thread class without any problems. Under which plateform? -- Frédéric ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Threads with PyQt. Qt's or Python's?
Hi, I always used QThread and emit() in order to communicate with main QThread without problems: thread = Thread(self) self.connet(thread, SIGNAL(Signal)) thread.start() 2009/1/19 Christoph Burgmer chri...@gmx.de: Am Monday, 19. January 2009 schrieb Giovanni Bajo: On 1/19/2009 3:13 PM, eliben wrote: I've seen various references to this issue before, but nothing to fully address it as I'd expect. Can you comment on the pros and cons of using QThread vs Python's threads with PyQt? I'll begin: on the surface, Python's threads make more sense because they're Qt independent and can be ported between apps that don't necessarily depend on Qt (for example a web version of a GUI app). The Python thread API is powerful enough for all uses, it seems. However, there are concerns. Perhaps QThreads are more efficient? Or maybe more tightly integrated with the other parts of PyQt, so it's easier to use them? It's mostly the same. The main difference is that QThreads are better integrated with Qt (asynchrnous signals/slots, event loop, etc.). Also, you can't use Qt from a Python thread (you can't for instance post event to the main thread through QApplication.postEvent): you need a QThread for that to work. I am doing a QCoreApplication.postEvent() out of run() from a threading.Thread class without any problems. Christoph ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Threads with PyQt. Qt's or Python's?
Sorry! thread = Thread(self) self.connet(thread, SIGNAL(Signal), self.Slot) thread.start() 2009/1/19 Sergio Jovani lese...@gmail.com: Hi, I always used QThread and emit() in order to communicate with main QThread without problems: thread = Thread(self) self.connet(thread, SIGNAL(Signal)) thread.start() 2009/1/19 Christoph Burgmer chri...@gmx.de: Am Monday, 19. January 2009 schrieb Giovanni Bajo: On 1/19/2009 3:13 PM, eliben wrote: I've seen various references to this issue before, but nothing to fully address it as I'd expect. Can you comment on the pros and cons of using QThread vs Python's threads with PyQt? I'll begin: on the surface, Python's threads make more sense because they're Qt independent and can be ported between apps that don't necessarily depend on Qt (for example a web version of a GUI app). The Python thread API is powerful enough for all uses, it seems. However, there are concerns. Perhaps QThreads are more efficient? Or maybe more tightly integrated with the other parts of PyQt, so it's easier to use them? It's mostly the same. The main difference is that QThreads are better integrated with Qt (asynchrnous signals/slots, event loop, etc.). Also, you can't use Qt from a Python thread (you can't for instance post event to the main thread through QApplication.postEvent): you need a QThread for that to work. I am doing a QCoreApplication.postEvent() out of run() from a threading.Thread class without any problems. Christoph ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Threads with PyQt. Qt's or Python's?
Am Monday, 19. January 2009 schrieben Sie: Le 19/1/2009, Christoph Burgmer chri...@gmx.de a écrit: I am doing a QCoreApplication.postEvent() out of run() from a threading.Thread class without any problems. Under which plateform? Linux. I initially made a short check if their was any argument against using Python threads with Qt and then dediced for the Python ones as: - learning Python threading helps you more in overall Python programming - documentation is at hand in the usual documentation style. Giovanni's response strikes me as it would be a serious annoyance if I had to change my threading model only to port my application to Windows and Mac. I don't even get any QPainter or other thread related warnings in my app, something which KDE throws out on a per minute basis. Christoph ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Threads with PyQt. Qt's or Python's?
On lundi 19 janvier 2009, Christoph Burgmer wrote: QCoreApplication.postEvent() out of run() from a threading.Thread class without any problems. Under which plateform? Linux. I initially made a short check if their was any argument against using Python threads with Qt and then dediced for the Python ones as: - learning Python threading helps you more in overall Python programming - documentation is at hand in the usual documentation style. Giovanni's response strikes me as it would be a serious annoyance if I had to change my threading model only to port my application to Windows and Mac. I don't even get any QPainter or other thread related warnings in my app, something which KDE throws out on a per minute basis. Strange you don't get any issues... As X11 is not thread-safe, you should get some X11 errors, leading to crashs. I use python threads, but I have a serializer to push all Qt calls on a queue, and this queue is processed from the main thread, using a QTimer timeout signal. But all this is true for Qt3, and things may have changed in Qt4... -- Frédéric http://www.gbiloba.org ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Threads with PyQt. Qt's or Python's?
On 1/19/2009 4:36 PM, Christoph Burgmer wrote: Am Monday, 19. January 2009 schrieb Giovanni Bajo: On 1/19/2009 3:13 PM, eliben wrote: I've seen various references to this issue before, but nothing to fully address it as I'd expect. Can you comment on the pros and cons of using QThread vs Python's threads with PyQt? I'll begin: on the surface, Python's threads make more sense because they're Qt independent and can be ported between apps that don't necessarily depend on Qt (for example a web version of a GUI app). The Python thread API is powerful enough for all uses, it seems. However, there are concerns. Perhaps QThreads are more efficient? Or maybe more tightly integrated with the other parts of PyQt, so it's easier to use them? It's mostly the same. The main difference is that QThreads are better integrated with Qt (asynchrnous signals/slots, event loop, etc.). Also, you can't use Qt from a Python thread (you can't for instance post event to the main thread through QApplication.postEvent): you need a QThread for that to work. I am doing a QCoreApplication.postEvent() out of run() from a threading.Thread class without any problems. That's only because you are lucky. It's not something that's officially supported and I have spent days debugging random crashes that turned out being Qt accesses from threads allocated by Python. I suggest you to fix your code. -- Giovanni Bajo Develer S.r.l. http://www.develer.com ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Threads with PyQt. Qt's or Python's?
On 1/19/2009 5:03 PM, Christoph Burgmer wrote: Giovanni's response strikes me as it would be a serious annoyance if I had to change my threading model only to port my application to Windows and Mac. I don't even get any QPainter or other thread related warnings in my app, something which KDE throws out on a per minute basis. You don't get any warning because nobody suggested Trolltech to add warning to detect the usage of an external threading library with Qt. With C++, you can see that it makes absolutely no sense to bring an external threading library instead of using Qt, so it's not a common error. -- Giovanni Bajo Develer S.r.l. http://www.develer.com ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Threads with PyQt. Qt's or Python's?
On 1/19/2009 5:37 PM, Frédéric wrote: I use python threads, but I have a serializer to push all Qt calls on a queue, and this queue is processed from the main thread, using a QTimer timeout signal. This would work on Qt4 as well, but of course it's not ideal as you need a timer to poll the queue. It's much easier to use QThreads and simply post the events (or use the asynchronous signals). Plus, you can now do non-trivial things from the secondary threads (eg: painting with QPainter over a QImage) so it's worth sitting down and analyzing all these possibilities before desiging the code with Qt4. This is the correct link to get a broad overview: http://doc.trolltech.com/4.4/threads.html -- Giovanni Bajo Develer S.r.l. http://www.develer.com ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Threads with PyQt. Qt's or Python's?
On lundi 19 janvier 2009, Giovanni Bajo wrote: On 1/19/2009 5:37 PM, Frédéric wrote: I use python threads, but I have a serializer to push all Qt calls on a queue, and this queue is processed from the main thread, using a QTimer timeout signal. This would work on Qt4 as well, but of course it's not ideal as you need a timer to poll the queue. It's much easier to use QThreads and simply post the events (or use the asynchronous signals). Plus, you can now do non-trivial things from the secondary threads (eg: painting with QPainter over a QImage) so it's worth sitting down and analyzing all these possibilities before desiging the code with Qt4. This is the correct link to get a broad overview: http://doc.trolltech.com/4.4/threads.html You convinced me ;o) As I plan to use the MVC-delegate pattern provided in Qt, I will need to have some Qt-dependent code in my model, so, better use all Qt features... -- Frédéric http://www.gbiloba.org ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Threads with PyQt. Qt's or Python's?
Am Tuesday, 20. January 2009 schrieb Giovanni Bajo: On 1/19/2009 4:36 PM, Christoph Burgmer wrote: [...] I am doing a QCoreApplication.postEvent() out of run() from a threading.Thread class without any problems. That's only because you are lucky. It's not something that's officially supported and I have spent days debugging random crashes that turned out being Qt accesses from threads allocated by Python. I suggest you to fix your code. We have an unlucky situation here, Qt documents neither say that mixing threading libraries is ok, nor does it say it could lead to clashes. Now guessing won't help, but I'll do it anyway: QCoreApplication::postEvent() is thread-safe and thus has the highest safety level one could whish for in the Qt threading system. It works by adding the event to the event queue and returning immediatelly. It's the main event loop that then takes over. Now from that I would assume the only clashes could occur when fiddeling with the event queue. Instead of assuming some magic done in every thread I rather believe that synchronisation is done in the local method, postEvent(). Now things going wrong would mean that synchronisation there does depend on the threads all adhering to the same special protocol, something that IMHO is not needed to complete this task. Anyway, if somebody should have a bit more indepth knowledge on that, please step up. Christoph ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt