2

I would like to capture error messages which are generated from a python module A. A is written in C++ and SWIG, and so I cannot capture Python's sys.stderr.

>>> import A
>>> A.func() # this prints an error message by C++ std::cerr.
this is an error message from module A

What I want to do are to suppress the error message and to change my script behavior according to the error type. But A.func() does not return error numbers.


Assuming that my use of contextlib below is correct, it did not help.

>>> import io
>>> f = io.StringIO()
>>> import contextlib
>>> with contextlib.redirect_stderr(f):
... no_return = A.func()
ERROR MESSAGE HERE
>>> f.getvalue()

>>>
Akira Okumura
  • 1,816
  • 2
  • 20
  • 41
  • why not use a try statement ? – gogaz Sep 07 '18 at 09:29
  • @gogaz That would still not catch output written to `std::cerr` or would it? – FlyingTeller Sep 07 '18 at 09:31
  • Does `contextlib redirect_stdout` work for you? In that case, this is a duplicate: https://stackoverflow.com/questions/6796492/temporarily-redirect-stdout-stderr – Reblochon Masque Sep 07 '18 at 09:37
  • It didn't work. I should have mentioned it. I will edit the original post. – Akira Okumura Sep 07 '18 at 09:45
  • 1
    You will need to mess with its low-level file descriptor to get at the real stderr. See the stuff about file descriptors in the os module docs, and check out this article about redirecting C-level stdout in Python. https://eli.thegreenplace.net/2015/redirecting-all-kinds-of-stdout-in-python/#id1 – PM 2Ring Sep 07 '18 at 10:07
  • Also see https://stackoverflow.com/a/17753573/4014959 – PM 2Ring Sep 07 '18 at 10:14

1 Answers1

0

Thank you @PM2Ring

https://eli.thegreenplace.net/2015/redirecting-all-kinds-of-stdout-in-python/#id1

With minor modifications: replacing all the stdout with stderr and supporting macOS as shown below, it worked perfectly as expected.

if sys.platform == 'darwin':
    c_stderr = ctypes.c_void_p.in_dll(libc, '__stderrp')
else:
    c_stderr = ctypes.c_void_p.in_dll(libc, 'stderr')
Akira Okumura
  • 1,816
  • 2
  • 20
  • 41