[PyQt] stdin processing

Simon Edwards simon at simonzone.com
Wed Nov 7 19:37:02 GMT 2007


Hi,

Vladimir Pouzanov wrote:
> Is there any way to read stdin line by line without blocking? My application
> receives data over stdin (one command per line) and should react immediately.

Your story sounds a lot like the world of confusion and pain I found 
myself in when I wanted to read a pipe in an async way. I couldn't find 
a way that actually worked in a decent way. Here is my non-decent way of 
reading a pipe. Pure distilled madness.


-----------------------------------------------
#!/usr/bin/python
import os
import sys
import time

from PyQt4 import QtCore

# Frequency to poll the file for more data.
POLL_INTERVAL = 250 #ms

# Maximum amount of time to use reading logs without returning to the 
main event loop.
MAX_TIME_SLICE=  0.1    # seconds

class LogReader(QtCore.QObject):
     def __init__(self, filename):
         QtCore.QObject.__init__(self)
         self.filename = filename

         self.log_file = None
         self.connectToFile()

     def connectToFile(self):
         if self.log_file is not None:
             gobject.source_remove(self.log_event_source)
             self.log_file.close()
             self.log_file = None

         self.log_file_fd = os.open(self.filename,os.O_RDONLY|os.O_NONBLOCK)
         self.log_file = os.fdopen(self.log_file_fd,"r")
         self.timer_id = self.startTimer(0)

     def timerEvent(self,event):
         if event.timerId()==self.timer_id:
             self.killTimer(self.timer_id)
             self.timer_id = None
             self.fileReady()
         else:
             QObject.timerEvent(self,event)

     def fileReady(self):
         try:
             enter_time = time.time()
             restart_time = POLL_INTERVAL
             while True:
                 data = self.log_file.readline()
                 if data=="":
                     break
                 self.emit(QtCore.SIGNAL("newLine"), data)

                 new_time = time.time()
                 if (new_time-enter_time) > MAX_TIME_SLICE:
                     restart_time = 0
                     break

             self.timer_id = self.startTimer(restart_time)

         except IOError,e:
             self.connectToFile()

     def handleLine(self, line):
         print line

def main():
     app = QtCore.QCoreApplication(sys.argv)
     log_reader = LogReader("/var/log/messages")
     app.exec_()

if __name__=="__main__":
     main()
-----------------------------------------------

-- 
Simon Edwards             | KDE-NL, Guidance tools, Guarddog Firewall
simon at simonzone.com       | http://www.simonzone.com/software/
Nijmegen, The Netherlands | "ZooTV? You made the right choice."


More information about the PyQt mailing list