I am trying to get subprocess output (on Windows) at the time the TimeoutExpired exception is raised. Any ideas?
try:
proc = subprocess.run(cmd,timeout=3)
except subprocess.TimeoutExpired:
print(???)
I am trying to get subprocess output (on Windows) at the time the TimeoutExpired exception is raised. Any ideas?
try:
proc = subprocess.run(cmd,timeout=3)
except subprocess.TimeoutExpired:
print(???)
You need to use Popen and subprocess.PIPE in order to catch the process output when timeout expires. In particular Popen.communicate is what you need. Here is an example
proc = subprocess.Popen(["ping", "192.168.1.1"],
stdout=subprocess.PIPE)
try:
output, error = proc.communicate(timeout=2)
except subprocess.TimeoutExpired:
proc.kill()
output, error = proc.communicate()
print(output)
print(error)
This will print the process output up to the time out expiration.
If you cannot use timeout
for whatever reason (one being a too old python version), here's my solution, which works with whatever python version:
subprocess
objectI'm using a python subprocess, running with the -u
(unbuffered) option:
transmitter.py: (test program which prints "hello xx" every 1/10th second)
import time
i=0
while True:
print("hello {}".format(i))
i += 1
time.sleep(0.1)
the program itself (timeout set to 1.5 second):
import subprocess,threading,time
def timeout(p,timeout):
time.sleep(timeout)
p.kill()
p = subprocess.Popen(["python","-u","transmitter.py"],stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
t = threading.Thread(target=timeout,args=(p,1.5))
t.start()
output = []
for line in p.stdout:
output.append(line.decode())
t.join()
print("".join(output))
In the end, after timeout, the program prints:
hello 0
hello 1
hello 2
hello 3
hello 4
hello 5
hello 6
hello 7
hello 8
hello 9
hello 10
hello 11
hello 12
hello 13
hello 14
Here is the way for capturing stdout for multiprocessing.Process
import app
import sys
import io
from multiprocessing import Process
def run_app(some_param):
sys.stdout = io.TextIOWrapper(open(sys.stdout.fileno(), 'wb', 0), write_through=True)
app.run()
app_process = Process(target=run_app, args=('some_param',))
app_process.start()
# Use app_process.termninate() for python <= 3.7.
app_process.kill()