Reputation: 33
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
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