Logging, console output, and file management for Python — simple by default, configurable for advanced workflows.
Project description
Logduo
Logging, console output, and file management for Python scripts and interactive sessions.
Simple by default, configurable for advanced logging workflows.
Platform: Tested on macOS, Windows, and Ubuntu.
Key Capabilities
- Manages output directories and log files
- Supports ANSI-styled and Rich console output while preserving readable plain-text logs
- Provides extensive
help()documentation and actionable error messages - Validates arguments to all Logduo methods and functions to prevent unexpected behavior
- Safely prunes old run directories containing a Logduo marker file
- Generates session artifacts: config_table.txt, config.json
- Captures JSONL event streams
- Creates dedicated log files via
new_logger() - Creates custom logging labels via
new_level() - Supports nested scripts via
log.join()andrun()
Quick Start (in script or interactive session)
from logduo import log
log("hello world")
log.warning("warning message")
If a message is logged before log.configure() is called, the logging session starts automatically using Logduo defaults and pyproject.toml settings.
Key default settings:
console_verbosity = 2andlog_verbosity = 2- Messages (other than TRACE and DEBUG) are sent to both the console and the main log file.
log_dir_path = "auto"- The
logsdirectory is placed in the project root if identified; otherwise, in the current working directory.
- The
log_file_layout = "run"- Logs are created in timestamped run directories.
keep = "off"- Previous run directories are not pruned automatically.
- If
keepis set to a positive integern, the newestnLogduo-marked run directories are kept and older run directories are pruned.
write_config_table = Trueconfig_table.txtis written with configuration values, descriptions, and allowed values.
Configure (Optional)
Recommendation: Place all regularly used configuration settings in pyproject.toml under [tool.logduo]
from pathlib import Path
from logduo import log
my_log_dir = Path("/absolute/path/to/my_log_dir")
log.configure(log_dir_path=my_log_dir, keep=3, console_verbosity=3, log_verbosity=3)
log("hello world")
Export Logduo Docs
Export bundled documentation and example scripts to a local logduo_docs/ directory:
log.export_logduo_docs()
Exported files include:
README.txtexamples/first_script.pyexamples/console_rendering.pyexamples/data_analysis.pyexamples/math_report_notation.pyexamples/nested_parent_script.pyexamples/nested_child_script.py
Help
-
Help is available for all Logduo methods and functions (displays in console only):
help(log.configure) -
Help includes examples, argument descriptions, and usage notes.
Typical Workflows
-
Debug session: By default, log.debug() includes the calling file name and line number at the start of each message. Disable with: log.configure(..., show_debug_source=False)
from logduo import log log.configure(log_verbosity=3, console_verbosity=3) log.debug(f"made it here: var = {var}") -
Create additional log files for dedicated output. Messages logged with
repare recorded in report.log and optionally mirrored to the console and/or main log file.rep = log.new_logger("report", to_console=True, to_main_log=False) rep("Question 1 answer:") -
Use the output directory to save plots, CSVs, reports, and other generated files
myplot_output_path = log.output_dir_path / "myplot.png" -
Close the session (required in interactive sessions, optional in scripts)
log.close()
Logduo Methods and Functions
-
Manage session:
log.configure()log.close()log.join()
-
Log levels:
log()orlog.info()log.trace()log.debug()log.success()log.warning()log.error()log.critical()log.exception()# ERROR + Traceback
-
Create custom log label:
log.new_level()# Create a custom label handled as an existing level; default = "INFO"
-
Create additional output:
log.new_logger()# Logduo-managed extra log filelog.new_loguru_sink()# Advanced Loguru sinklog.export_logduo_docs()
-
Access paths:
log.output_dir_pathlog.main_log_file_path
-
Utility function:
run()# Execute child script or importable module in a parent script or an interactive session.- Import with:
from logduo import run
Behavior
Prefixes
-
One prefix per log event.
-
Console and log files have independent prefix settings:
console_prefix,log_prefixoff→ No prefix. Wrapped lines align flush leftlevel→ Prefix shows level. Wrapped lines align under message.timestamp→ Prefix shows timestamp and level. Wrapped lines align under message.source→ Prefix shows timestamp, level, and source. Wrapped lines align under source.
-
Example console output:
console_prefix="source",show_pid_in_console=True,console_wrap_width=8016:30:40.371 | WARNING | example_2.py:382 - (15408:i1) Logduo is designed for data scientists, researchers, students, and Python developers who want readable console output, organized log files, and minimal logging setup.
Message Rendering
- Strings without
\n: Displayed inline with the prefix.- Console: Wrapped (displayed line width =
console_wrap_width). - Log files: Wrapped only if
log_wrap_widthis set to a positive integer. Default is"off".
- Console: Wrapped (displayed line width =
- Strings containing
\n: Displayed as block flush left below prefix. Line breaks are honored.-
This preserves the full available line width for tables, panels, JSON, tracebacks, and other structured content.
-
Use manual indenting or Rich
Paddingif indent behavior is desired:indent = " " * 13 log( f"{indent}Step 1: Load data\n" f"{indent}Step 2: Clean data\n" )
-
- ANSI-styled strings and Rich
Textobjects are rendered on the console and written as plain text in log files. - Other Rich objects, such as
Panel, are rendered on the console but displayed as placeholders in log files.- For more examples, use
log.export_logduo_docs()and seeconsole_rendering.py.
- For more examples, use
Log File Name and Location
- Log file name:
- Custom
log_file_name:log.configure(log_file_name="my_name.ext") - Default
log_file_name: calling script stem +.log- If the calling script is my_file.py: default
log_file_name→my_file.log - If no calling script is found, as expected in interactive sessions: default
log_file_name→session.log
- If the calling script is my_file.py: default
- Custom
- Location of log directory:
- Custom
log_dir_path:log.configure(log_dir_path=my_log_dir) - Default
log_dir_path:- If pyproject.toml is not detected:
log_dir_path= current working directory / "logs" - If pyproject.toml is detected:
log_dir_path= parent directory of pyproject.toml / "logs"
- If pyproject.toml is not detected:
- Custom
- Location of log file: set by
log_file_layout:"flat","script", or"run"(default)- flat:
log_dir_path/log_file_name - script:
log_dir_path/script_stem/log_file_name - run:
log_dir_path/script_stem/run_yyyy_mm_dd__hh_mm_ss/log_file_name
- flat:
Note:
- If no calling script is found,
script_stemis set to"session"whenlog_file_layout="script"or"run" - If
log_file_pathis provided, it specifies the complete log file pathlog_file_pathoverrideslog_file_layout,log_dir_path, andlog_file_namelog_file_pathdoes not overridelog_file_mode("write","append", or"timestamped")log.output_dir_pathis set to the parent oflog_file_path
Loguru Integration
-
Logduo uses Loguru as its underlying file-sink engine.
-
The following Loguru sink options can be passed through
log.configure():rotation: start a new log file when a size/time rule is met. Example:rotation="10 MB"orrotation="1 week". Userotation="off"for no rotation (default ="off").retention: remove older rotated log files when a retention rule is met. Example:retention="14 days"orretention=5. This applies to rotated files, not to Logduo run-directory pruning (default ="off").compression: compress rotated log files. Example:compression="zip". This applies to rotated files, not the active log file (default ="off").enqueue: write logs through a background queue. Useful for thread/process safety (default =True).catch: catch logging errors instead of letting them crash the program (default =True).backtrace: show extended traceback context for exceptions (default =False).diagnose: include extra variable/context information in exception tracebacks (default =False).
-
Logduo performs message formatting, wrapping, routing, session management, and Rich integration before messages reach Loguru.
-
Use
log.new_logger()when you want a normal Logduo-managed extra log file. -
Use
log.new_loguru_sink()when you want direct Loguru control, such as:- using custom Loguru filters
- adding extra Loguru sinks
- sending selected events to separate destinations
- passing options directly to
logger.add()
-
Sinks added with
log.new_loguru_sink()are advanced/pass-through sinks. They are not managed like standard Logduo main logs ornew_logger()files.
Quality Assurance
Logduo is validated using:
- pytest, with over 500 individual tests
- Ruff
- mypy
- Vulture
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file logduo-0.1.2.tar.gz.
File metadata
- Download URL: logduo-0.1.2.tar.gz
- Upload date:
- Size: 116.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c5add3113e1719d6d2c1a2ca53529a9b13d87ae643799fbc90dc13fdd5b0c357
|
|
| MD5 |
e55f96ed703fe9b78fe7413de7667149
|
|
| BLAKE2b-256 |
b6825799734131e65cad522c8e20f7e4033e72f902fd749f79ba611c81f1d208
|
File details
Details for the file logduo-0.1.2-py3-none-any.whl.
File metadata
- Download URL: logduo-0.1.2-py3-none-any.whl
- Upload date:
- Size: 143.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4a537c106d23abe3d289f5b3702be3c5772a3f040b15b91f1c7ed8048d2f7779
|
|
| MD5 |
a1c46a4b6775b75a68cac9c14dcb4a05
|
|
| BLAKE2b-256 |
2ec220c2d4533847d5200066d986fecc6dd4bb66233fdf67045a69dbbcc53c4c
|