Skip to content

Commit 31aa7dd

Browse files
committed
Add a 'timeout' argument to subprocess.Popen.
If the timeout expires before the subprocess exits, the wait method and the communicate method will raise a subprocess.TimeoutExpired exception. When used with communicate, it is possible to catch the exception, kill the process, and retry the communicate and receive any output written to stdout or stderr.
1 parent 4169826 commit 31aa7dd

File tree

4 files changed

+367
-98
lines changed

4 files changed

+367
-98
lines changed

Doc/library/subprocess.rst

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -249,50 +249,65 @@ Convenience Functions
249249
This module also defines four shortcut functions:
250250

251251

252-
.. function:: call(*popenargs, **kwargs)
252+
.. function:: call(*popenargs, timeout=None, **kwargs)
253253

254254
Run command with arguments. Wait for command to complete, then return the
255255
:attr:`returncode` attribute.
256256

257-
The arguments are the same as for the :class:`Popen` constructor. Example::
257+
The arguments are the same as for the :class:`Popen` constructor, with the
258+
exception of the *timeout* argument, which is given to :meth:`Popen.wait`.
259+
Example::
258260

259261
>>> retcode = subprocess.call(["ls", "-l"])
260262

263+
If the timeout expires, the child process will be killed and then waited for
264+
again. The :exc:`TimeoutExpired` exception will be re-raised after the child
265+
process has terminated.
266+
261267
.. warning::
262268

263269
Like :meth:`Popen.wait`, this will deadlock when using
264270
``stdout=PIPE`` and/or ``stderr=PIPE`` and the child process
265271
generates enough output to a pipe such that it blocks waiting
266272
for the OS pipe buffer to accept more data.
267273

274+
.. versionchanged:: 3.2
275+
*timeout* was added.
276+
268277

269-
.. function:: check_call(*popenargs, **kwargs)
278+
.. function:: check_call(*popenargs, timeout=None, **kwargs)
270279

271280
Run command with arguments. Wait for command to complete. If the exit code was
272281
zero then return, otherwise raise :exc:`CalledProcessError`. The
273282
:exc:`CalledProcessError` object will have the return code in the
274283
:attr:`returncode` attribute.
275284

276-
The arguments are the same as for the :class:`Popen` constructor. Example::
285+
The arguments are the same as for the :func:`call` function. Example::
277286

278287
>>> subprocess.check_call(["ls", "-l"])
279288
0
280289

290+
As in the :func:`call` function, if the timeout expires, the child process
291+
will be killed and the wait retried. The :exc:`TimeoutExpired` exception
292+
will be re-raised after the child process has terminated.
293+
281294
.. warning::
282295

283296
See the warning for :func:`call`.
284297

298+
.. versionchanged:: 3.2
299+
*timeout* was added.
285300

286-
.. function:: check_output(*popenargs, **kwargs)
301+
302+
.. function:: check_output(*popenargs, timeout=None, **kwargs)
287303

288304
Run command with arguments and return its output as a byte string.
289305

290306
If the exit code was non-zero it raises a :exc:`CalledProcessError`. The
291307
:exc:`CalledProcessError` object will have the return code in the
292-
:attr:`returncode`
293-
attribute and output in the :attr:`output` attribute.
308+
:attr:`returncode` attribute and output in the :attr:`output` attribute.
294309

295-
The arguments are the same as for the :class:`Popen` constructor. Example::
310+
The arguments are the same as for the :func:`call` function. Example::
296311

297312
>>> subprocess.check_output(["ls", "-l", "/dev/null"])
298313
b'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n'
@@ -305,8 +320,17 @@ This module also defines four shortcut functions:
305320
... stderr=subprocess.STDOUT)
306321
b'ls: non_existent_file: No such file or directory\n'
307322

323+
As in the :func:`call` function, if the timeout expires, the child process
324+
will be killed and the wait retried. The :exc:`TimeoutExpired` exception
325+
will be re-raised after the child process has terminated. The output from
326+
the child process so far will be in the :attr:`output` attribute of the
327+
exception.
328+
308329
.. versionadded:: 3.1
309330

331+
.. versionchanged:: 3.2
332+
*timeout* was added.
333+
310334

311335
.. function:: getstatusoutput(cmd)
312336

@@ -359,6 +383,10 @@ arguments.
359383
check_call() will raise :exc:`CalledProcessError`, if the called process returns
360384
a non-zero return code.
361385

386+
All of the functions and methods that accept a *timeout* parameter, such as
387+
:func:`call` and :meth:`Popen.communicate` will raise :exc:`TimeoutExpired` if
388+
the timeout expires before the process exits.
389+
362390

363391
Security
364392
^^^^^^^^
@@ -380,23 +408,30 @@ Instances of the :class:`Popen` class have the following methods:
380408
attribute.
381409

382410

383-
.. method:: Popen.wait()
411+
.. method:: Popen.wait(timeout=None)
384412

385413
Wait for child process to terminate. Set and return :attr:`returncode`
386414
attribute.
387415

416+
If the process does not terminate after *timeout* seconds, raise a
417+
:exc:`TimeoutExpired` exception. It is safe to catch this exception and
418+
retry the wait.
419+
388420
.. warning::
389421

390422
This will deadlock when using ``stdout=PIPE`` and/or
391423
``stderr=PIPE`` and the child process generates enough output to
392424
a pipe such that it blocks waiting for the OS pipe buffer to
393425
accept more data. Use :meth:`communicate` to avoid that.
394426

427+
.. versionchanged:: 3.2
428+
*timeout* was added.
395429

396-
.. method:: Popen.communicate(input=None)
430+
431+
.. method:: Popen.communicate(input=None, timeout=None)
397432

398433
Interact with process: Send data to stdin. Read data from stdout and stderr,
399-
until end-of-file is reached. Wait for process to terminate. The optional
434+
until end-of-file is reached. Wait for process to terminate. The optional
400435
*input* argument should be a byte string to be sent to the child process, or
401436
``None``, if no data should be sent to the child.
402437

@@ -407,11 +442,29 @@ Instances of the :class:`Popen` class have the following methods:
407442
``None`` in the result tuple, you need to give ``stdout=PIPE`` and/or
408443
``stderr=PIPE`` too.
409444

445+
If the process does not terminate after *timeout* seconds, a
446+
:exc:`TimeoutExpired` exception will be raised. Catching this exception and
447+
retrying communication will not lose any output.
448+
449+
The child process is not killed if the timeout expires, so in order to
450+
cleanup properly a well-behaved application should kill the child process and
451+
finish communication::
452+
453+
proc = subprocess.Popen(...)
454+
try:
455+
outs, errs = proc.communicate(timeout=15)
456+
except TimeoutExpired:
457+
proc.kill()
458+
outs, errs = proc.communicate()
459+
410460
.. note::
411461

412462
The data read is buffered in memory, so do not use this method if the data
413463
size is large or unlimited.
414464

465+
.. versionchanged:: 3.2
466+
*timeout* was added.
467+
415468

416469
.. method:: Popen.send_signal(signal)
417470

0 commit comments

Comments
 (0)