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

system-integration.mddocs/

0

# System Integration

1

2

Forward C-level output to Python's sys.stdout/stderr streams, enabling integration with existing Python output handling systems like Jupyter notebooks, IPython, and logging frameworks.

3

4

## Capabilities

5

6

### System Stream Forwarding

7

8

Forward C-level stdout/stderr to Python sys streams without creating intermediate buffers.

9

10

```python { .api }

11

def sys_pipes(encoding='utf-8', bufsize=None):

12

"""Redirect C-level stdout/stderr to sys.stdout/stderr

13

14

Args:

15

encoding: Text encoding for output (default: 'utf-8')

16

bufsize: Pipe buffer size in bytes (default: auto-detected)

17

18

Returns:

19

Context manager that forwards C output to sys streams

20

21

Note:

22

This is useful when sys.stdout/stderr are already being forwarded

23

somewhere, e.g., in a Jupyter kernel. DO NOT USE if sys.stdout and

24

sys.stderr are not already being forwarded.

25

"""

26

```

27

28

Example usage:

29

30

```python

31

import sys

32

from wurlitzer import sys_pipes

33

34

# Ensure sys.stdout is being handled (e.g., in Jupyter)

35

with sys_pipes():

36

# C-level output will appear in the same place as Python print()

37

c_function_with_output()

38

print("This Python output and C output appear together")

39

```

40

41

### Jupyter/IPython Integration

42

43

Seamlessly integrate C-level output with Jupyter notebook cell outputs.

44

45

```python

46

from wurlitzer import sys_pipes

47

48

# In a Jupyter notebook cell

49

with sys_pipes():

50

# C library calls now appear in cell output

51

scientific_c_library.compute_results()

52

numpy_function_with_c_warnings()

53

```

54

55

### Combined with Python Output

56

57

Mix C-level and Python output in the same stream for unified logging.

58

59

```python

60

import sys

61

from wurlitzer import sys_pipes

62

63

def debug_function():

64

print("Python: Starting computation")

65

66

with sys_pipes():

67

c_computation_library.process() # C output mixed with Python

68

69

print("Python: Computation complete")

70

```

71

72

### Custom Stream Redirection

73

74

Use sys_pipes when sys.stdout/stderr have been redirected to custom handlers.

75

76

```python

77

import sys

78

from io import StringIO

79

from wurlitzer import sys_pipes

80

81

# Redirect Python sys streams

82

captured_output = StringIO()

83

original_stdout = sys.stdout

84

sys.stdout = captured_output

85

86

try:

87

with sys_pipes():

88

# Both Python and C output go to captured_output

89

print("Python output")

90

c_function_call() # C output

91

finally:

92

sys.stdout = original_stdout

93

94

all_output = captured_output.getvalue()

95

```

96

97

## Integration Patterns

98

99

### Testing Framework Integration

100

101

Integrate with testing frameworks that capture sys.stdout/stderr:

102

103

```python

104

import pytest

105

from wurlitzer import sys_pipes

106

107

def test_c_function_output(capsys):

108

with sys_pipes():

109

my_c_extension.function_under_test()

110

111

captured = capsys.readouterr()

112

assert "expected C output" in captured.out

113

```

114

115

### Logging Framework Integration

116

117

Forward C output through Python's logging system:

118

119

```python

120

import logging

121

import sys

122

from io import StringIO

123

from wurlitzer import sys_pipes

124

125

class LoggingHandler(logging.StreamHandler):

126

def __init__(self):

127

super().__init__(StringIO())

128

129

def emit(self, record):

130

# Process log records that may include C output

131

super().emit(record)

132

133

# Setup logging to capture sys output

134

logger = logging.getLogger()

135

handler = LoggingHandler()

136

logger.addHandler(handler)

137

138

# Redirect sys.stdout to logger

139

sys.stdout = handler.stream

140

141

with sys_pipes():

142

c_function_call() # Output goes through logging system

143

```

144

145

### Web Application Integration

146

147

Integrate with web frameworks where sys.stdout is redirected:

148

149

```python

150

from wurlitzer import sys_pipes

151

import flask

152

153

app = flask.Flask(__name__)

154

155

@app.route('/process')

156

def process_data():

157

output_buffer = []

158

159

with sys_pipes():

160

# C processing output captured in web context

161

result = c_data_processor.analyze(request.data)

162

163

return {"result": result, "processing_complete": True}

164

```

165

166

## Error Handling and Validation

167

168

### Stream Validation

169

170

sys_pipes includes validation to prevent infinite recursion:

171

172

```python

173

import sys

174

from wurlitzer import sys_pipes

175

176

# This will raise ValueError to prevent infinite recursion

177

try:

178

# When sys.stdout is the same as sys.__stdout__

179

with sys_pipes():

180

pass

181

except ValueError as e:

182

print(f"Cannot forward streams: {e}")

183

# Use regular pipes() instead

184

from wurlitzer import pipes

185

with pipes():

186

c_function_call()

187

```

188

189

### Fallback Patterns

190

191

Graceful degradation when sys_pipes cannot be used:

192

193

```python

194

from wurlitzer import sys_pipes, pipes

195

196

def safe_c_call():

197

try:

198

with sys_pipes():

199

return c_function_call()

200

except ValueError:

201

# Fallback to regular pipes

202

with pipes() as (out, err):

203

result = c_function_call()

204

205

# Handle captured output manually

206

stdout_content = out.read()

207

if stdout_content:

208

print(stdout_content, end='')

209

210

return result

211

```

212

213

### Thread Safety

214

215

sys_pipes is thread-safe and works correctly in multi-threaded environments:

216

217

```python

218

import threading

219

from wurlitzer import sys_pipes

220

221

def worker_thread():

222

with sys_pipes():

223

thread_specific_c_function()

224

225

# Multiple threads can safely use sys_pipes

226

threads = [threading.Thread(target=worker_thread) for _ in range(4)]

227

for t in threads:

228

t.start()

229

for t in threads:

230

t.join()

231

```