0
# Permanent Redirection
1
2
Enable and disable permanent C-level output forwarding without context managers, useful for global configuration and long-running applications.
3
4
## Capabilities
5
6
### Enable Permanent Redirection
7
8
Start permanent forwarding of all C-level output to Python sys streams.
9
10
```python { .api }
11
def sys_pipes_forever(encoding='utf-8', bufsize=None):
12
"""Redirect all C output to sys.stdout/err permanently.
13
14
Args:
15
encoding: Text encoding for output (default: 'utf-8')
16
bufsize: Pipe buffer size in bytes (default: auto-detected)
17
18
Note:
19
This is not a context manager; it turns on C-forwarding permanently
20
until stop_sys_pipes() is called.
21
"""
22
```
23
24
Example usage:
25
26
```python
27
from wurlitzer import sys_pipes_forever
28
29
# Enable permanent redirection at application startup
30
sys_pipes_forever()
31
32
# All subsequent C-level output is forwarded
33
c_library_function_1()
34
other_c_operations()
35
c_library_function_2()
36
37
# Output forwarding continues until explicitly stopped
38
```
39
40
### Disable Permanent Redirection
41
42
Stop permanent redirection and restore original C-level stream behavior.
43
44
```python { .api }
45
def stop_sys_pipes():
46
"""Stop permanent redirection started by sys_pipes_forever"""
47
```
48
49
Example usage:
50
51
```python
52
from wurlitzer import sys_pipes_forever, stop_sys_pipes
53
54
# Start permanent forwarding
55
sys_pipes_forever()
56
57
# ... application runs with C output forwarded ...
58
59
# Stop forwarding at application shutdown or when no longer needed
60
stop_sys_pipes()
61
62
# C output now goes back to original destinations
63
```
64
65
### Thread-Safe Global State
66
67
The permanent redirection system uses thread-safe locks to manage global state.
68
69
```python
70
from wurlitzer import sys_pipes_forever, stop_sys_pipes
71
import threading
72
73
def worker_function():
74
# Multiple threads can safely call these functions
75
sys_pipes_forever() # Only activates once globally
76
77
c_work_function()
78
79
stop_sys_pipes() # Only deactivates when last thread calls it
80
81
# Safe in multi-threaded environments
82
threads = [threading.Thread(target=worker_function) for _ in range(3)]
83
for t in threads:
84
t.start()
85
for t in threads:
86
t.join()
87
```
88
89
## Usage Patterns
90
91
### Application Initialization
92
93
Configure C-level output forwarding during application startup:
94
95
```python
96
from wurlitzer import sys_pipes_forever
97
import logging
98
99
def initialize_app():
100
# Setup logging
101
logging.basicConfig(level=logging.INFO)
102
103
# Enable C output forwarding for entire application
104
sys_pipes_forever()
105
106
print("Application initialized with C output forwarding")
107
108
def main():
109
initialize_app()
110
111
# All C library calls throughout the application
112
# will have their output forwarded to sys.stdout/stderr
113
run_application_logic()
114
```
115
116
### Service/Daemon Applications
117
118
Long-running services that need consistent C output handling:
119
120
```python
121
import signal
122
import sys
123
from wurlitzer import sys_pipes_forever, stop_sys_pipes
124
125
class ServiceApplication:
126
def __init__(self):
127
# Enable C output forwarding for service lifetime
128
sys_pipes_forever()
129
130
def start(self):
131
# Setup signal handlers for clean shutdown
132
signal.signal(signal.SIGTERM, self._shutdown)
133
signal.signal(signal.SIGINT, self._shutdown)
134
135
# Service main loop
136
while self.running:
137
self.process_requests()
138
139
def _shutdown(self, signum, frame):
140
print("Shutting down service...")
141
stop_sys_pipes()
142
self.running = False
143
sys.exit(0)
144
145
def process_requests(self):
146
# C library calls have output forwarded automatically
147
c_request_processor.handle_batch()
148
```
149
150
### Testing Setup/Teardown
151
152
Configure test environments with global C output forwarding:
153
154
```python
155
import pytest
156
from wurlitzer import sys_pipes_forever, stop_sys_pipes
157
158
@pytest.fixture(scope="session", autouse=True)
159
def setup_c_output_forwarding():
160
"""Enable C output forwarding for entire test session"""
161
sys_pipes_forever()
162
yield
163
stop_sys_pipes()
164
165
def test_c_function_1():
166
# C output automatically forwarded, captured by pytest
167
c_function_under_test()
168
169
def test_c_function_2():
170
# All tests benefit from automatic C output forwarding
171
another_c_function()
172
```
173
174
### Library Initialization
175
176
Enable forwarding when importing libraries that use C extensions:
177
178
```python
179
# mylib/__init__.py
180
from wurlitzer import sys_pipes_forever
181
182
# Automatically enable C output forwarding when library is imported
183
sys_pipes_forever()
184
185
from .core import main_functions
186
from .extensions import c_extensions
187
188
__all__ = ['main_functions', 'c_extensions']
189
```
190
191
### Conditional Activation
192
193
Enable permanent redirection based on environment or configuration:
194
195
```python
196
import os
197
from wurlitzer import sys_pipes_forever
198
199
def configure_output_handling():
200
# Enable based on environment variable
201
if os.getenv('ENABLE_C_OUTPUT_FORWARDING', '').lower() == 'true':
202
sys_pipes_forever()
203
print("C output forwarding enabled")
204
205
# Or based on configuration file
206
if config.get('debug', {}).get('capture_c_output', False):
207
sys_pipes_forever()
208
print("Debug mode: C output forwarding enabled")
209
210
# Call during application setup
211
configure_output_handling()
212
```
213
214
## State Management
215
216
### Idempotent Operations
217
218
Multiple calls to sys_pipes_forever() are safe and idempotent:
219
220
```python
221
from wurlitzer import sys_pipes_forever, stop_sys_pipes
222
223
# Multiple calls don't create multiple redirections
224
sys_pipes_forever() # Enables forwarding
225
sys_pipes_forever() # No additional effect
226
sys_pipes_forever() # Still no additional effect
227
228
stop_sys_pipes() # Disables forwarding
229
stop_sys_pipes() # Safe to call multiple times
230
```
231
232
### Status Checking
233
234
Check if permanent redirection is currently active:
235
236
```python
237
from wurlitzer import sys_pipes_forever, stop_sys_pipes
238
import wurlitzer
239
240
# Check global state (internal variable)
241
def is_permanent_forwarding_active():
242
return wurlitzer._mighty_wurlitzer is not None
243
244
# Example usage
245
if not is_permanent_forwarding_active():
246
sys_pipes_forever()
247
248
# Later...
249
if is_permanent_forwarding_active():
250
print("C output is being forwarded")
251
stop_sys_pipes()
252
```
253
254
### Context Integration
255
256
Combine permanent redirection with temporary context managers:
257
258
```python
259
from wurlitzer import sys_pipes_forever, stop_sys_pipes, pipes
260
261
# Global forwarding for most operations
262
sys_pipes_forever()
263
264
# Temporary override for specific capture
265
with pipes() as (out, err):
266
# This temporarily overrides the permanent forwarding
267
special_c_function()
268
269
captured_output = out.read()
270
271
# Back to permanent forwarding after context manager exits
272
normal_c_operations()
273
```