In Python, capturing process output with contextlib.redirect_stdout / contextlib.redirect_stderr, or manual redirection of sys.stdout
and sys.stderr
works only when sys file objects are actually being used by the producer to write to standard output or error. If data streams are referred directly, for instance by an underlying C/C++ library invoked by the interpreter, hence eliding sys file objects, these methods are inadequate.
Fortunately, the os
module lays on a number of file descriptor operations that can be availed to capture the actual standard streams. The capture_stream.py gist defines a context manager that is capable of capturing the given IO stream
(e.g. sys.stdout
or sys.stderr
) and populates the returned Captured
's data
property on exit.
Following snippet exemplifies the usage of capture_stream
context manager to capture OpenCV imread
errors, not exposed by the Python API:
import cv2
import sys
from pathlib import Path
root = Path(r'/home/user/Pictures/')
for img in root.rglob(r'*.jpg'):
with capture_stream(sys.stderr) as error:
fatal = cv2.imread(img.as_posix()) is None
if error.data:
print(f'{img}: {error.data}')
The context manager implementation follows the idea published in "In python, how to capture the stdout from a c++ shared library to a variable" and simply wraps the code available therein, so all credit goes to the original publisher!