So I have this simple POC
import subprocess
proc = subprocess.run('cmd', timeout=1, shell=True, capture_output=True)
it is not raising a TimeoutError after the given interval (which is 1 second in this case)
and it seems like the timeout flag in the subprocess.run()
is working just fine in Linux but seems to produce bugs in windows
For example
import subprocess
proc = subprocess.run('ping -n 10 127.0.0.1', shell=True, capture_output=True, timeout=1)
Seems to not raise the timeout error untill after the command completes
Edit of what I tried and the output:
C:\Users\zaid2\Documents>type t.py
import subprocess
import time
s = time.time()
try:
roc = subprocess.run('ping -n 10 127.0.0.1', shell=True, capture_output=True, timeout=1)
finally:
print(f'\nFinished in {round(time.time() - s)} seconds.\n\n')
C:\Users\zaid2\Documents>python t.py
Finished in 9 seconds.
Traceback (most recent call last):
File "C:\Users\zaid2\Documents\t.py", line 6, in <module>
roc = subprocess.run('ping -n 10 127.0.0.1', shell=True, capture_output=True, timeout=1)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\zaid2\AppData\Local\Programs\Python\Python311\Lib\subprocess.py", line 550, in run
stdout, stderr = process.communicate(input, timeout=timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\zaid2\AppData\Local\Programs\Python\Python311\Lib\subprocess.py", line 1209, in communicate
stdout, stderr = self._communicate(input, endtime, timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\zaid2\AppData\Local\Programs\Python\Python311\Lib\subprocess.py", line 1628, in _communicate
raise TimeoutExpired(self.args, orig_timeout)
subprocess.TimeoutExpired: Command 'ping -n 10 127.0.0.1' timed out after 1 seconds
C:\Users\zaid2\Documents>python --version
Python 3.11.8
made my own timeout implementation using Popen
import subprocess
import time
def run_command_with_timeout(cmd, timeout):
start_time = time.time()
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
while time.time() - start_time < timeout:
if process.poll() is not None:
return process.communicate()
time.sleep(0.1)
else:
process.kill()
raise TimeoutError
if __name__ == "__main__":
stdout, stderr = run_command_with_timeout('ping -n 10 google.com', timeout=1)
if stdout:
print(stdout.decode())
if stderr:
print(stderr.decode())
print("Process finished")