[PyQt] Simple polling monitor application

David Hoese dhoese at gmail.com
Fri Jul 19 14:37:57 BST 2013


Hi Eric,

One thing that was recommended to me when I started doing monitoring 
GUIs was to use a QTimer of 0 to call the polling function. To do this 
for your code, move everything in the "while True" into it's own 
function and make it run on a per-iteration way. So in your example, 
"count" would become an instance attribute and I think that's it.

Then in the run method you would create a QTimer and set it to call that 
new per-iteration function:

     self.my_timer = QtCore.QTimer()
     self.my_timer.timeout.connect(self.get_stuff)
     self.my_timer.start(0) # or some amount of delay

The 0 delay makes it continuously add the "get_stuff" method to the 
event loop. This should do what you want. You may run in to trouble when 
closing the GUI if your polling does any kind of blocking. Once you tell 
the thread to stop (an event in the event loop) the thread won't get to 
that event until the blocking operation is complete. Depending on the 
length of the blocking, your GUI could hang on close for a little bit. 
There are ways around this, but I haven't found one that I love. 
Hopefully that made sense.

Please CC me in any replies, thanks.

-Dave

P.S. I'll point you to a blog post about not subclassing QThread as the 
preferred method (get your stuff working first): 
http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/

On 7/19/2013 6:00 AM, eric.frederich at gmail.com wrote:
> Hello,
>
> I wrote an example monitoring application where I have a separate
> thread monitoring something via an external process which could take
> 20ms to run or it could take 2 seconds to run.
> Right now I have it just doing a time.sleep(1) for the example.
>
> I want this monitoring to continuously happen.
> It is an endless (while True) loop.
> I'd prefer to use a QTimer but don't know how to get a QTimer to
> trigger something in another thread.
> The work needs to be done in another thread to keep the GUI responsive.
>
> Can someone point me in the right direction or modify the following
> code to use a QTimer rather than an infinite loop with a sleep
> command?
>
>
> #!/usr/bin/env python
>
> from PyQt4.QtCore import *
> from PyQt4.QtGui import *
>
> import time
> from datetime import datetime
>
> class MyThread(QThread):
>      def __init__(self, parent=None):
>          super(MyThread, self).__init__(parent)
>
>      def run(self):
>          count = 0
>          while True:
>              count += 1
>              print 'do_something ', count, 'begin'
>              time.sleep(1)
>              self.emit(SIGNAL("new_info"), str(count) + ' ' +
> str(datetime.now()))
>              print 'do_something ', count, 'end'
>
> class MyWidget(QWidget):
>      def __init__(self, parent=None):
>          super(MyWidget, self).__init__(parent)
>          self.setWindowTitle("Monitor")
>          layout = QVBoxLayout()
>          self.line = QLineEdit()
>          layout.addWidget(self.line)
>          self.setLayout(layout)
>
>          self.mon = MyThread()
>          self.connect(self.mon, SIGNAL("new_info"), self.on_new_info)
>          self.mon.start()
>
>      def on_new_info(self, info):
>          print 'got new info', info
>          self.line.setText(info)
>
> if __name__ == '__main__':
>      import sys
>      app = QApplication(sys.argv)
>      gm = MyWidget()
>      gm.show()
>      sys.exit(app.exec_())


More information about the PyQt mailing list