Handling multiplexed streams

Note

The following instruction assume you’re interested in getting output from an exec command. These instruction are similarly applicable to the output of attach.

First create a container that runs in the background:

>>> client = docker.from_env()
>>> container = client.containers.run(
...     'bfirsh/reticulate-splines', detach=True)

Prepare the command we are going to use. It prints “hello stdout” in stdout, followed by “hello stderr” in stderr:

>>> cmd = '/bin/sh -c "echo hello stdout ; echo hello stderr >&2"'

We’ll run this command with all four the combinations of stream and demux.

With stream=False and demux=False, the output is a string that contains both the stdout and the stderr output:

>>> res = container.exec_run(cmd, stream=False, demux=False)
>>> res.output
b'hello stderr\nhello stdout\n'

With stream=True, and demux=False, the output is a generator that yields strings containing the output of both stdout and stderr:

>>> res = container.exec_run(cmd, stream=True, demux=False)
>>> next(res.output)
b'hello stdout\n'
>>> next(res.output)
b'hello stderr\n'
>>> next(res.output)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

With stream=True and demux=True, the generator now separates the streams, and yield tuples (stdout, stderr):

>>> res = container.exec_run(cmd, stream=True, demux=True)
>>> next(res.output)
(b'hello stdout\n', None)
>>> next(res.output)
(None, b'hello stderr\n')
>>> next(res.output)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

Finally, with stream=False and demux=True, the output is a tuple (stdout, stderr):

>>> res = container.exec_run(cmd, stream=False, demux=True)
>>> res.output
(b'hello stdout\n', b'hello stderr\n')