Source From Here
Question
Here's the Python code to run an arbitrary command returning its stdout data, or raise an exception on non-zero exit codes:
communicate is used to wait for the process to exit:
The subprocess module does not support timeout--ability to kill a process running for more than X number of seconds--therefore, communicate may take forever to run.
What is the simplest way to implement timeouts in a Python program meant to run on Windows and Linux?
HowTo
In Python 3.3+:
output is a byte string that contains command's merged stdout, stderr data.
check_output raises CalledProcessError on non-zero exit status as specified in the question's text unlike proc.communicate() method.
I've removed shell=True because it is often used unnecessarily. You can always add it back if cmd indeed requires it. If you add shell=True i.e., if the child process spawns its own descendants; check_output() can return much later than the timeout indicates, see Subprocess timeout failure.
For a quick demonstration:
Another approach is to use Python threading module to wrap your command execution. e.g.:
- test.py
Execution result:
Here's the Python code to run an arbitrary command returning its stdout data, or raise an exception on non-zero exit codes:
- proc = subprocess.Popen(
- cmd,
- stderr=subprocess.STDOUT, # Merge stdout and stderr
- stdout=subprocess.PIPE,
- shell=True)
- stdoutdata, stderrdata = proc.communicate()
What is the simplest way to implement timeouts in a Python program meant to run on Windows and Linux?
HowTo
In Python 3.3+:
- from subprocess import STDOUT, check_output
- output = check_output(cmd, stderr=STDOUT, timeout=seconds)
check_output raises CalledProcessError on non-zero exit status as specified in the question's text unlike proc.communicate() method.
I've removed shell=True because it is often used unnecessarily. You can always add it back if cmd indeed requires it. If you add shell=True i.e., if the child process spawns its own descendants; check_output() can return much later than the timeout indicates, see Subprocess timeout failure.
For a quick demonstration:
Another approach is to use Python threading module to wrap your command execution. e.g.:
- test.py
- #!/usr/bin/env python3
- import subprocess, threading
- class Command(object):
- def __init__(self, cmd):
- self.cmd = cmd
- self.process = None
- def run(self, timeout):
- def target():
- print('Thread started')
- self.process = subprocess.Popen(self.cmd, shell=True)
- self.process.communicate()
- print('Thread finished')
- thread = threading.Thread(target=target)
- thread.start()
- thread.join(timeout)
- if thread.is_alive():
- print('Terminating process')
- self.process.terminate()
- thread.join()
- print(f"command:{self.cmd}\nWith rc={self.process.returncode} (timeout={timeout})")
- command = Command("echo 'Process started'; sleep 2; echo 'Process finished'")
- command.run(timeout=3)
- command.run(timeout=1)
沒有留言:
張貼留言