How to timeout in Python

Chao Ren
2 min readSep 18, 2018

--

Timeout is very useful when you want to limit the max time for calling a function or running a command. Here are my two Python implementations. (I’m using Python 3.6.5).

Use multiprocessing to timeout a Python function

Use one process to keep time/check timeout and another process to call this Python function.

import time
from itertools import count
from multiprocessing import Process
def inc_forever():
print('Starting function inc_forever()...')
while True:
time.sleep(1)
print(next(counter))
def return_zero():
print('Starting function return_zero()...')
return 0
if __name__ == '__main__':
# counter is an infinite iterator
counter = count(0)
p1 = Process(target=inc_forever, name='Process_inc_forever')
p2 = Process(target=return_zero, name='Process_return_zero')
p1.start()
p2.start()
p1.join(timeout=5)
p2.join(timeout=5)
p1.terminate()
p2.terminate()
if p1.exitcode is None:
print(f'Oops, {p1} timeouts!')
if p2.exitcode == 0:
print(f'{p2} is luck and finishes in 5 seconds!')

The output is as follows. The exit code tells whether the function is a timeout (exitcode=None) or finished.

Starting function inc_forever()...
Starting function return_zero()...
0
1
2
3
4
Oops, <Process(Process_inc_forever, started)> timeouts!
<Process(Process_return_zero, stopped)> is luck and finishes in 5 seconds!

Use subprocess to timeout an external command

Since Python 3.5, there’s a handy and recommendedrun() API in subprocess module, which has built-in timeout support.

import subprocessr = subprocess.run(['echo', 'hello timeout'], timeout=5)
print(
f'''type(r)={type(r)},
r.args={r.args},
r.returncode={r.returncode},
r.stdout={r.stdout},
r.stderr={r.stderr}'''
)
try:
r = subprocess.run(['ping', 'www.google.com'], timeout=5)
except subprocess.TimeoutExpired as e:
print(e)

When timeout, it raises a TimeoutExpired exception.

hello timeout
type(r)=<class 'subprocess.CompletedProcess'>,
r.args=['echo', 'hello timeout'],
r.returncode=0,
r.stdout=None,
r.stderr=None
PING www.google.com (216.58.194.164) 56(84) bytes of data.
64 bytes from ...: icmp_seq=1 ttl=54 time=10.4 ms
64 bytes from ...: icmp_seq=2 ttl=54 time=5.90 ms
64 bytes from ...: icmp_seq=3 ttl=54 time=6.19 ms
64 bytes from ...: icmp_seq=4 ttl=54 time=9.04 ms
64 bytes from ...: icmp_seq=5 ttl=54 time=16.7 ms
Command '['ping', 'www.google.com']' timed out after 5 seconds

For UNIX, there’s another way to use the signal module to signal a handler to raise an exception after 5 seconds, but I think it’s a little low-level and not straightforward.

--

--