source: src/Python/capture_c_contextmanager.py@ 13e5be

stable v1.7.0
Last change on this file since 13e5be was 6b7765, checked in by Frederik Heber <frederik.heber@…>, 4 years ago

Added small lib to capture stdout and stderr in jupyter.

  • we need to pipe output into a temporary file as otherwise it will only be printed in the console and not in the jupyter cells.
  • Property mode set to 100644
File size: 2.5 KB
Line 
1# This is the answer to a question asked on stackoverflow:
2# https://stackoverflow.com/questions/35745541/how-to-get-printed-output-from-ctypes-c-functions-into-jupyter-ipython-notebook
3#
4# This is the code by Denilson Sá Maia
5
6import io
7import os
8import sys
9import tempfile
10from contextlib import contextmanager
11
12from pyMoleCuilder_capture import fflush_stderr, fflush_stdout, \
13 disable_stderr_buffering, disable_stdout_buffering
14
15@contextmanager
16def capture_std_out_err(encoding='utf8'):
17 # Flushing, it's a good practice.
18 sys.stdout.flush()
19 sys.stderr.flush()
20 fflush_stdout()
21 fflush_stderr()
22
23 # We need to use a actual file because we need the file descriptor number.
24 with tempfile.TemporaryFile(buffering=0) as temp:
25 # Saving a copy of the original stdout.
26 prev_sys_stdout = sys.stdout
27 prev_stdout_fd = os.dup(1)
28 os.close(1)
29
30 prev_sys_stderr = sys.stderr
31 prev_stderr_fd = os.dup(2)
32 os.close(2)
33
34 # Duplicating the temporary file fd into the stdout fd.
35 # In other words, replacing the stdout.
36 os.dup2(temp.fileno(), 1)
37 os.dup2(temp.fileno(), 2)
38 log_to_fileno(temp.fileno())
39
40 # Replacing sys.stdout for Python code.
41 #
42 # IPython Notebook version of sys.stdout is actually an
43 # in-memory OutStream, so it does not have a file descriptor.
44 # We need to replace sys.stdout so that interleaved Python
45 # and C output gets captured in the correct order.
46 #
47 # We enable line_buffering to force a flush after each line.
48 # And write_through to force all data to be passed through the
49 # wrapper directly into the binary temporary file.
50 temp_wrapper = io.TextIOWrapper(
51 temp, encoding=encoding, line_buffering=True, write_through=True)
52 sys.stdout = temp_wrapper
53 sys.stderr = temp_wrapper
54
55 # Disabling buffering of C stdout.
56 disable_stdout_buffering()
57 disable_stderr_buffering()
58
59 yield
60
61 # Must flush to clear the C library buffer.
62 fflush_stdout()
63 fflush_stderr()
64
65 # Restoring stdout.
66 os.dup2(prev_stdout_fd, 1)
67 os.close(prev_stdout_fd)
68 sys.stdout = prev_sys_stdout
69
70 os.dup2(prev_stderr_fd, 2)
71 os.close(prev_stderr_fd)
72 sys.stderr = prev_sys_stderr
73 temp.fileno(1)
74
75 # Printing the captured output.
76 temp_wrapper.seek(0)
77 print(temp_wrapper.read(), end='')
Note: See TracBrowser for help on using the repository browser.