|
5 | 5 | Author : Breno Farias da Silva |
6 | 6 | Created : 2025-12-11 |
7 | 7 | Description : |
8 | | - This module implements a dual-channel logging system designed to capture |
9 | | - all console output produced by Python scripts while preserving ANSI colors |
10 | | - in the terminal and removing them from the log file. |
11 | | -
|
12 | | - It provides consistent, color-safe logging across interactive terminals, |
13 | | - background executions, CI pipelines, Makefile pipelines, and nohup/systemd |
14 | | - environments. |
15 | | -
|
16 | | - Key features include: |
17 | | - - Automatic ANSI color stripping for log files |
18 | | - - Full compatibility with interactive and non-interactive terminals |
19 | | - - Mirrored output: terminal (colored) + log file (clean) |
20 | | - - Optional integration by assigning it to sys.stdout/sys.stderr |
| 8 | + Dual-channel logger that mirrors console output to both the terminal |
| 9 | + (preserving ANSI color sequences when the terminal is a TTY) and a |
| 10 | + sanitized log file (ANSI sequences removed). Designed for use in |
| 11 | + interactive sessions, background jobs, CI pipelines and Makefile runs. |
| 12 | +
|
| 13 | + Behavior: |
| 14 | + - When attached to `sys.stdout`/`sys.stderr` the logger writes colored |
| 15 | + output to the controlling terminal (when available) and a color-free |
| 16 | + record to the specified log file. |
| 17 | + - ANSI escape sequences are removed from the file output using a |
| 18 | + conservative regex; lines are flushed immediately to keep logs live. |
| 19 | + - Provides minimal API: `write()`, `flush()` and `close()` so it can be |
| 20 | + used as a drop-in replacement for `sys.stdout`. |
21 | 21 |
|
22 | 22 | Usage: |
23 | | - 1. Create a Logger instance: |
24 | | -
|
25 | | - from logger import Logger |
26 | | - logger = Logger("./Logs/output.log", clean=True) |
27 | | -
|
28 | | - 2. (Optional) Redirect all stdout/stderr to the logger: |
29 | | -
|
30 | | - sys.stdout = logger |
31 | | - sys.stderr = logger |
32 | | -
|
33 | | - 3. Print normally: |
34 | | -
|
35 | | - print("\x1b[92mHello World\x1b[0m") |
36 | | -
|
37 | | - Terminal shows colored output. |
38 | | - Log file receives the same text without ANSI escape sequences. |
39 | | -
|
40 | | -Outputs: |
41 | | - - <path>.log file with fully sanitized (color-free) log output |
42 | | - - Real-time terminal output with correct ANSI handling |
| 23 | + from Logger import Logger |
| 24 | + logger = Logger("./Logs/myrun.log", clean=True) |
| 25 | + sys.stdout = logger # optional: redirect all prints to logger |
43 | 26 |
|
44 | | -TODOs: |
45 | | - - Timestamp prefixing for each log line |
46 | | - - File rotation or size-based log splitting |
47 | | - - CLI flag to force color on/off |
48 | | - - Optional JSON-structured logs |
| 27 | +Notes & TODOs: |
| 28 | + - Consider adding timestamps, log rotation, and JSON output format. |
| 29 | + - The ANSI regex is intentionally simple; adjust if you need broader support. |
49 | 30 |
|
50 | 31 | Dependencies: |
51 | | - - Python >= 3.8 |
52 | | - - colorama (optional but recommended for Windows) |
| 32 | + - Python >= 3.8 (no external runtime dependencies required) |
53 | 33 |
|
54 | | -Assumptions & Notes: |
55 | | - - ANSI escape sequences follow the regex: \x1B\[[0-9;]*[a-zA-Z] |
56 | | - - Log file always stores clean output |
57 | | - - When stdout is not a TTY, color output is automatically disabled |
| 34 | +Assumptions: |
| 35 | + - The log file will contain cleaned, human-readable text (no ANSI codes). |
| 36 | + - The logger is safe for short-lived scripts and long-running processes. |
58 | 37 | """ |
59 | 38 |
|
60 | 39 | import os # For interacting with the filesystem |
@@ -123,12 +102,13 @@ def write(self, message): |
123 | 102 | pass # Silent fail |
124 | 103 |
|
125 | 104 | try: # Write to terminal: colored when TTY, cleaned otherwise |
126 | | - if self.is_tty: # Terminal supports colors |
127 | | - sys.__stdout__.write(out) # Write colored message |
128 | | - sys.__stdout__.flush() # Flush immediately |
129 | | - else: # Terminal does not support colors |
130 | | - sys.__stdout__.write(clean_out) # Write cleaned message |
131 | | - sys.__stdout__.flush() # Flush immediately |
| 105 | + if sys.__stdout__ is not None: |
| 106 | + if self.is_tty: # Terminal supports colors |
| 107 | + sys.__stdout__.write(out) # Write colored message |
| 108 | + sys.__stdout__.flush() # Flush immediately |
| 109 | + else: # Terminal does not support colors |
| 110 | + sys.__stdout__.write(clean_out) # Write cleaned message |
| 111 | + sys.__stdout__.flush() # Flush immediately |
132 | 112 | except Exception: # Fail silently to avoid breaking user code |
133 | 113 | pass # Silent fail |
134 | 114 |
|
|
0 commit comments