How to start a process with a timeout and still get stdout at runtime

Necessity:

  • Time out after X seconds and kill the process (and all processes that it opened) if the timeout is reached before the process finishes gracefully.
  • Read the current output at run time.
  • Work with processes that produce output, those that do not work, and those that produce output, and then stop producing it (for example, get stuck).
  • Running on Windows.
  • Running on Python 3.5.2.

The Python 3 subprocess module has a timeout , and I also tried and implemented a timeout myself, using a timer and using threads, but it does not work with output. readline() blocking or not? readlines() definitely waits for the process to complete before splashing out all the output that I don't need (I need to continue).

I'm close to switching to node.js: - (

+5
source share
2 answers

I would use asyncio for this task.

Reading IO from a process, as in this accepted anwser: How to pass stdout / stderr from a child process using asyncio and get its exit code after?

(I do not want to completely copy it here)

Wrap it in timeout:

 async def killer(trans, timeout): await asyncio.sleep(timeout) trans.kill() print ('killed!!') trans, *other_stuff = loop.run_until_complete( loop.subprocess_exec( SubprocessProtocol, 'py', '-3', '-c', 'import time; time.sleep(6); print("Yay!")' , ) ) asyncio.ensure_future(killer(trans, 5)) # 5 seconds timeout for the kill loop.run_forever() 

Good luck ...

+4
source

Use 2 python script below.

  • The .py wizard will use Popen to start a new process and start a watcher thread that will kill the process after 3.0 seconds.

  • The slave must call the flush method if there is no new line in the data written to stdout (a flash is also called in the windows '\n' ).

Be careful, the time module is not a high-precision timer.

The process loading time in extreme cases can exceed 3.0 seconds (reading the executable file from a flash drive with USB 1.0)

Master.py

 import subprocess, threading, time def watcher(proc, delay): time.sleep(delay) proc.kill() proc = subprocess.Popen('python Slave.py', stdout = subprocess.PIPE) threading.Thread(target = watcher, args = (proc, 3.0)).start() data = bytearray() while proc: chunk = proc.stdout.read(1) if not chunk: break data.extend(chunk) print(data) 

Slave.py

 import time, sys while True: time.sleep(0.1) sys.stdout.write('aaaa') sys.stdout.flush() 
0
source

All Articles