There is a class for simple reading stdout and stderr of any process.
The next problems are solved:
- Reading blocking when trying to read stdout/stderr of a process.
- Stopping process properly. Just call one of the methods:
terminate()orkill().
- 2.7
- 3.x
pip install https://github.com/sergzach/readingproc/archive/master.zip
Let's get stdout of cat myfile. To read iterate with iter_run() method.
from readingproc import ReadingProc
proc = ReadingProc('cat myfile')
proc.start()
for data in proc.iter_run():
print(data.stdout.decode())Tailing file and return control when there is no new information for 10 seconds.
from readingproc import ReadingProc, ChunkTimeout
proc = ReadingProc('tail -f myfile')
proc.start()
try:
for data in proc.iter_run(chunk_timeout=10.0):
print(data.stdout.decode())
except ChunkTimeout:
# there were no new lines for the last 10 secs
print('Error. No new lines for 10 seconds.') Reading output of several processes in one loop.
from readingproc import ReadingSet, ReadingProc
# download all javascript files using by a google.com
url = 'https://google.com'
html_content = ''
# firstly download the main page
proc = ReadingProc('wget -O {}'.format(url))
for proc in proc.iter_run():
html_content += proc.stdout.decode()
# parse all js urls at the page
re_js = '<script src=[\'"]'Read output for 60 seconds. If time is up then TotalTimeout occurs.
from readingproc import ReadingProc, TotalTimeout
proc = ReadingProc('cat myfile; sleep 70; echo OK')
proc.start()
try:
for data in proc.iter_run(total_timeout=60.0):
print(data.stdout.decode())
except TotalTimeout:
print('60 seconds passed but the process still alive.')
# lets terminate the process
proc.terminate()Getting control when expired, make some actions and continue reading.
from readingproc import ReadingProc, TotalTimeout
expired = False
proc = ReadingProc('cat myfile; sleep 70; echo OK')
proc.start()
try:
for data in proc.iter_run(total_timeout=60.0):
print(data.stdout.decode())
except TotalTimeout:
expired = True
# process is not finished yet... Continue reading.
for data in proc.iter_run():
print(data.stdout.decode())
finally:
print('Process done, expiration status: {}.'.format(expired))Reading pipes of many processes in one loop.
from readingproc import ReadingProc, ReadingSet
patient_procs = {
'John': ReadingProc('tail -f /tmp/patient1.log'),
'Mike': ReadingProc('tail -f /tmp/patient2.log'),
'Helene': ReadingProc('tail -f /tmp/patient3.log')
}
reading_set = ReadingSet()
for log in patient_procs:
proc = ReadingProc('tail -f {}'.format(log))
reading_set.add(patient_logs)
# start all reading processes which have not been started yet
reading_set.start_all()
for data in reading_set.iter_run(total_timeout=10.0, chunk_timeout=1.0):
# ReadingProc supports the equal comparing
if data.reading_proc == patient_procs['John']:
# extracting necessary data
is_total_timeout = data.is_total_timeout
is_chunk_timeout = data.is_chunk_timeout
# stdout and stderr are None in case of any timeout
stdout = data.stdout
stderr = data.stderr
if is_chunk_timeout:
print('Alarm! John\'s device does not respond.')
# do not listen Mike and Helene any more
reading_set -= patient_procs['Mike']
reading_set -= patient_procs['Helene']
# terminate all the processes which are alive
reading_set.terminate_all()The examples are for Python 3. For Python 2 you create the same code. data.stdout and data.stderr in Python 2 have str type, in Python 3 they both have bytes type (processes send bytes which can be decoded into strings).