or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-implementation.mdindex.mdipython-integration.mdoutput-capture.mdpermanent-redirection.mdsystem-integration.md

output-capture.mddocs/

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

```