rcdtx
rcdtx

Reputation: 33

Parse continuous sub process and write to file in Python

I am looking to have my Python (2.7.5) script continuously read and parse timestamps and other info from a continuous sub process, do a timestamp diff with system time and write that to a text file. I will be calling the camonitor utility from EPICS channel access as the process. This acts similar to something like top which will continuously run and update data until the process is killed. After googling and looking through many posts on here this is what I have. I think I am missing something that will continuously append data to my text file.

import subprocess
from Queue import Queue, Empty
from threading import Thread
from datetime import datetime
import time

class NonBlockingStreamReader:

    def __init__(self, stream):
        '''
        stream: stream to read from such as stdout
        '''
        self._s = stream
        self._q = Queue()

        def _populateQueue(stream, queue):
            '''
            collect lines from 'stream' and put them in 'queue'
            '''
            while True:
                line = stream.readline()
                if line:
                    queue.put(line)
                else:
                    raise UnexpectedEndOfStream

        self._t = Thread(target = _populateQueue, args = (self._s, self._q))
        self._t.daemon = True
        self._t.start() # start collecting lines from thel stream

    def readline(self, timeout = None):
        try:
            return self._q.get(block = timeout is not None, timeout = timeout)

        except Empty:
            return None


class UnexpectedEndOfStream(Exception): pass

def caMonitor(signalList):

     cmd = ["camonitor"]
     # add signals to the camonitor command
     cmd.extend(signalList)

     print(cmd)

     process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
     # wrap process.stdout with a NonBlockingStreamReader object:
     nbsr = NonBlockingStreamReader(process.stdout)

     # get the output for  X seconds
     t_end = time.time() + 1

     fmt = "%H:%M:%S.%f"

     while time.time() < t_end:
        try:
              output = nbsr.readline(0.05)
              # 0.05 secs to get the results
              '''
              if not output:
                 print ('[No data]')
                 break
              '''
              signal = output[0:16]
              timestamp = output[42:57]
              now = datetime.now()
              sysTime = now.strftime("%H:%M:%S.%f")

              tstamp1 = datetime.strptime(timestamp, fmt)
              tstamp2 = datetime.strptime(sysTime, fmt)

              if tstamp1 > tstamp2:
                 td = tstamp1 - tstamp2
              else:
                 td = tstamp2 - tstamp1

              print(signal + ' ' + timestamp + ' systime ' + sysTime + ' delta: ' + str(td))

              with open('camonlog.log', 'a+') as f:
                 f.write(signal + ' ' + timestamp + ' systime ' + sysTime + ' delta: ' + str(td) + '\n')

        except TypeError:
              print "no data"

Upvotes: 0

Views: 238

Answers (1)

ideoutrea
ideoutrea

Reputation: 199

In the class NonBlockingStreamReader populateQueue method will raise UnexpectedEndOfStream exception if the stream don’t have any data, the thread will stop to watch the stream.

Define the method like this:

def _populateQueue(stream, queue):
    while True:
        line = stream.readline()
        if line:
            queue.put(line)
        else:
            time.sleep(1)

Upvotes: 1

Related Questions