Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Timeout on subprocess readline in Python

I have a small issue that I'm not quite sure how to solve. Here is a minimal example:

What I have

scan_process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) while(some_criterium):     line = scan_process.stdout.readline()     some_criterium = do_something(line) 

What I would like

scan_process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) while(some_criterium):     line = scan_process.stdout.readline()     if nothing_happens_after_10s:         break     else:         some_criterium = do_something(line) 

I read a line from a subprocess and do something with it. How can I exit if no line arrived after a fixed time interval?

like image 475
Tom Avatar asked May 25 '12 14:05

Tom


People also ask

Is it possible to timeout a subprocess in Python 2?

The other day I ran into a use case where I needed to communicate with a subprocess I had started but I needed it to timeout. Unfortunately, Python 2 does not have a way to timeout the communicate method call so it just blocks until it either returns or the process itself closes.

What is timeoutexpired in Python?

Python 3.5 added the run function which accepts a timeout parameter. According to the documentation, it will be passed to the subprocess’s communicate method and TimeoutExpired exception will be raised should the process time out.

How to read a line asynchronously using streamreader in Python?

See "Subprocess" in the docs. There is a high-level interface asyncio.create_subprocess_exec () that returns Process objects that allows to read a line asynchroniosly using StreamReader.readline () coroutine (with async / await Python 3.5+ syntax ): Each step could be limited by timeout seconds if necessary. Try the asyncproc module. For example:

Where can I use the timeout parameter in Python?

Interestingly enough, the timeout parameter was added to the subprocess module in Python 3.3. You can use it in subprocess.call, check_output, and check_call. It's also available in Popen.wait ().


1 Answers

Thanks for all the answers!

I found a way to solve my problem by simply using select.poll to peek into standard output.

import select ... scan_process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) poll_obj = select.poll() poll_obj.register(scan_process.stdout, select.POLLIN) while(some_criterium and not time_limit):     poll_result = poll_obj.poll(0)     if poll_result:         line = scan_process.stdout.readline()         some_criterium = do_something(line)     update(time_limit) 
like image 169
Tom Avatar answered Sep 28 '22 09:09

Tom