A Python logging utility designed for parallel processing applications. It provides an interactive curses-based terminal UI to monitor and debug logs from multiple threads in real-time.
- Thread-aware logging: Automatically tracks and organizes logs by thread name
- Interactive TUI: Navigate between different threads using arrow keys
- Real-time updates: Logs are displayed as they're generated
- Easy integration: Simple API with context manager support
- Thread-safe: Built with thread safety in mind using locks and events
pip install parallel_loggerfrom concurrent.futures import ThreadPoolExecutor
from time import sleep
from parallel_logger import display_session, pl_print
def task(n):
pl_print(f"Task {n} starting")
sleep(n * 3)
pl_print(f"Task {n} completed")
return n * n
with display_session():
with ThreadPoolExecutor(max_workers=3) as executor:
for i in range(6):
executor.submit(task, i)from parallel_logger import start_display, stop_display, pl_print
start_display()
try:
# Your parallel code here
pl_print("Hello from thread!")
finally:
stop_display()Records a message for the current thread. Works like Python's built-in print() function but routes output to the parallel logger instead of stdout.
Parameters:
*args: Values to printsep: Separator between values (default:" ")end: String appended after the last value (default:"\n")
Context manager that runs the curses viewer in a helper thread for the duration of the block.
Parameters:
refresh_rate: How often to refresh the display in seconds (default:0.1)
Example:
with display_session(refresh_rate=0.05):
# Your parallel code here
passLaunches the curses UI on a helper thread and returns the thread object.
Parameters:
refresh_rate: How often to refresh the display in seconds (default:0.1)
Returns: threading.Thread object
Programmatically stops the display loop if it is running.
Runs the interactive viewer. This is a blocking call that will run until stopped.
Parameters:
refresh_rate: How often to refresh the display in seconds (default:0.1)
Checks if the UI thread is currently alive.
Returns: bool - True if the display is running, False otherwise
When the display is running, you can interact with it using:
- Left Arrow (←): Switch to previous thread
- Right Arrow (→): Switch to next thread
- Q: Quit the display
The UI shows:
- Current thread name and position (e.g., "Thread 2/5: ThreadPoolExecutor-0_1")
- All logs from the selected thread
- Navigation instructions in the footer
- Python >= 3.13
- Standard library only (no external dependencies)
See the included example.py for a complete working demonstration:
python example.py --mode context
python example.py --mode manualThe library uses a singleton ParallelLogger instance that:
- Collects log messages from each thread separately
- Maintains thread order based on first log appearance
- Renders logs in a curses-based terminal UI
- Allows interactive navigation between thread logs
All logging is thread-safe using threading.Lock() and coordination between threads is managed with threading.Event() objects.
See LICENSE file for details.
Luca Mattiazzi