0
# Output Capture
1
2
Context manager-based C-level output capture for temporary redirection of stdout and stderr streams.
3
4
## Capabilities
5
6
### Basic Output Capture
7
8
Capture both stdout and stderr in separate streams using the default PIPE mode.
9
10
```python { .api }
11
def pipes(stdout=PIPE, stderr=PIPE, encoding='utf-8', bufsize=None):
12
"""Capture C-level stdout/stderr in a context manager.
13
14
Args:
15
stdout: None, PIPE, Writable, or Logger object (default: PIPE)
16
stderr: None, PIPE, STDOUT, Writable, or Logger object (default: PIPE)
17
encoding: Text encoding for captured output (default: 'utf-8')
18
bufsize: Pipe buffer size in bytes (default: auto-detected)
19
20
Returns:
21
Tuple of (stdout, stderr) streams when used as context manager
22
"""
23
```
24
25
Example usage:
26
27
```python
28
from wurlitzer import pipes
29
30
with pipes() as (out, err):
31
# C-level function calls here
32
libc.printf(b"Hello from C stdout\n")
33
libc.fprintf(stderr_fd, b"Error from C stderr\n")
34
35
stdout_content = out.read() # "Hello from C stdout\n"
36
stderr_content = err.read() # "Error from C stderr\n"
37
```
38
39
### Combined Stream Capture
40
41
Redirect both stdout and stderr to a single destination using the STDOUT constant.
42
43
```python
44
from wurlitzer import pipes, STDOUT
45
46
with pipes(stderr=STDOUT) as (out, err):
47
# Both stdout and stderr go to 'out'
48
call_c_function_with_mixed_output()
49
# err will be None
50
51
combined_output = out.read()
52
```
53
54
### Custom Stream Destinations
55
56
Direct output to specific file-like objects, files, or StringIO instances.
57
58
```python
59
from io import StringIO
60
from wurlitzer import pipes, STDOUT
61
62
# Redirect to custom StringIO
63
output_buffer = StringIO()
64
with pipes(stdout=output_buffer, stderr=STDOUT):
65
c_function_call()
66
67
captured_text = output_buffer.getvalue()
68
```
69
70
### File Output
71
72
Write captured output directly to files for persistent storage.
73
74
```python
75
from wurlitzer import pipes, STDOUT
76
77
with open("output.log", "w") as logfile:
78
with pipes(stdout=logfile, stderr=STDOUT):
79
long_running_c_process()
80
# Output is written directly to output.log
81
```
82
83
### Logger Integration
84
85
Forward captured output to Python logging objects with configurable log levels.
86
87
```python { .api }
88
def pipes(stdout=Logger, stderr=Logger, encoding='utf-8', bufsize=None):
89
"""When Logger objects are passed, each line becomes a log message.
90
91
stdout Logger messages: INFO level
92
stderr Logger messages: ERROR level
93
"""
94
```
95
96
Example with logging:
97
98
```python
99
import logging
100
from wurlitzer import pipes, STDOUT
101
102
logger = logging.getLogger("c_output")
103
logger.setLevel(logging.INFO)
104
105
# Add handlers as needed
106
handler = logging.FileHandler("c_output.log")
107
logger.addHandler(handler)
108
109
with pipes(stdout=logger, stderr=STDOUT):
110
c_function_with_debug_output()
111
# Each line of C output becomes a log entry
112
```
113
114
### Binary Output Mode
115
116
Capture raw bytes without text encoding for binary data handling.
117
118
```python
119
from wurlitzer import pipes
120
121
with pipes(encoding=None) as (out, err):
122
c_function_producing_binary_data()
123
124
binary_stdout = out.read() # Returns bytes object
125
binary_stderr = err.read() # Returns bytes object
126
```
127
128
### Buffer Size Configuration
129
130
Control pipe buffer sizes for performance optimization, especially on Linux systems.
131
132
```python
133
from wurlitzer import pipes
134
135
# Large buffer for high-volume output
136
with pipes(bufsize=1024*1024) as (out, err): # 1MB buffer
137
c_function_with_lots_of_output()
138
139
# Disable buffer size setting
140
with pipes(bufsize=0) as (out, err):
141
c_function_call()
142
```
143
144
## Usage Patterns
145
146
### Scientific Computing
147
148
Capture output from NumPy, SciPy, or other libraries with C extensions:
149
150
```python
151
import numpy as np
152
from wurlitzer import pipes
153
154
with pipes() as (out, err):
155
# NumPy operations that may produce C-level warnings
156
result = np.linalg.solve(matrix_a, vector_b)
157
158
warnings = err.read()
159
if warnings:
160
print(f"NumPy warnings: {warnings}")
161
```
162
163
### Testing and Debugging
164
165
Verify that C-level functions produce expected output:
166
167
```python
168
from wurlitzer import pipes
169
170
def test_c_function_output():
171
with pipes() as (out, err):
172
my_c_extension.debug_function()
173
174
output = out.read()
175
assert "Expected debug message" in output
176
assert err.read() == "" # No errors
177
```
178
179
### Jupyter Notebook Usage
180
181
Clean output capture in notebook environments:
182
183
```python
184
from wurlitzer import pipes
185
186
with pipes() as (out, err):
187
# C library calls won't pollute notebook output
188
some_noisy_c_library.process_data()
189
190
# Examine output programmatically
191
if out.read().strip():
192
print("C function produced output")
193
```