{"id":2106,"library":"logistro","title":"Logistro","description":"Logistro is an extremely light wrapper over Python's standard `logging` module, providing sensible defaults for logging configuration. It simplifies common logging setups and includes specialized functionality like `getPipeLogger()` for piping subprocess stderr to the main logger. The library is currently at version 2.0.1 and maintains an active development status, with recent releases focused on minor fixes and metadata updates.","status":"active","version":"2.0.1","language":"en","source_language":"en","source_url":"https://github.com/geopozo/logistro","tags":["logging","utility","wrapper","python-standard-library"],"install":[{"cmd":"pip install logistro","lang":"bash","label":"Install stable release"}],"dependencies":[],"imports":[{"note":"This is the primary way to obtain a logger, and it ensures Logistro's default configuration is applied.","symbol":"getLogger","correct":"import logistro\nlogger = logistro.getLogger(__name__)"},{"note":"Used for routing subprocess stderr to the Logistro logger.","symbol":"getPipeLogger","correct":"import logistro\npipe, logger = logistro.getPipeLogger(__name__ + '-subprocess')"},{"note":"Configures all loggers to output in JSON format. Must be called before any logging output.","symbol":"set_structured","correct":"import logistro\nlogistro.set_structured()"},{"note":"Configures all loggers to output in human-readable format (default). Must be called before any logging output.","symbol":"set_human","correct":"import logistro\nlogistro.set_human()"}],"quickstart":{"code":"import logistro\nimport os\nimport subprocess\n\n# Basic logger setup (automatically configured by getLogger)\nlogger = logistro.getLogger(__name__)\n\nlogger.debug2(\"This is a custom debug level (more verbose)\")\nlogger.debug(\"This is a standard debug message\")\nlogger.info(\"Application started\")\n\ntry:\n    # Example with getPipeLogger for subprocesses\n    # Note: In a real app, manage 'cli_command' securely (e.g., using shlex.split)\n    cli_command = [os.environ.get('EXAMPLE_SUBPROCESS_COMMAND', 'ls'), '-l']\n    pipe, sub_logger = logistro.getPipeLogger(__name__ + '-subprocess')\n    process = subprocess.Popen(cli_command, stderr=pipe)\n    process.wait() # Wait for the subprocess to finish\n    os.close(pipe) # Crucial to close the pipe after use\n    sub_logger.info(\"Subprocess finished with exit code: %s\", process.returncode)\n\n    raise ValueError(\"Something went wrong\")\nexcept ValueError as e:\n    logger.exception(\"An error occurred: %s\", e)\n\n# Switch to structured logging mid-execution (affects subsequent logs)\nlogistro.set_structured()\nlogger.info(\"This message is now structured (JSON)\", user_id=\"123\", event=\"test_event\")","lang":"python","description":"This quickstart demonstrates how to initialize Logistro, use its custom logging levels (`debug2`), integrate with subprocesses using `getPipeLogger()`, and dynamically switch between human-readable and structured (JSON) output formats."},"warnings":[{"fix":"Call `logistro.set_structured()` or `logistro.set_human()` early in your application's lifecycle, ideally before `logistro.getLogger()` is first called for the root logger. If changing mid-execution, re-coerce the logger: `logistro.set_structured(); logistro.coerce_logger(logistro.getLogger())`.","message":"When switching between human-readable (`set_human()`) and structured (`set_structured()`) logging formats, these functions must be called *before* any other logging calls. Calling them mid-execution with an existing logger requires an additional step (`logistro.coerce_logger(logistro.getLogger())`) to ensure the formatter is updated.","severity":"gotcha","affected_versions":"2.0.0+"},{"fix":"Do not pass a `format` argument to `logistro.betterConfig()`. Instead, use `logistro.set_human()` (default) or `logistro.set_structured()` to control the output format globally.","message":"The `logistro.betterConfig()` function, which is implicitly called by `logistro.getLogger()`, accepts most arguments identical to Python's standard `logging.basicConfig()` but *ignores* the `format` argument. This is because Logistro manages its own formatting based on `set_human()` or `set_structured()`.","severity":"gotcha","affected_versions":"2.0.0+"},{"fix":"Always ensure `os.close(pipe)` is called after the subprocess that uses the pipe has terminated and its output has been consumed or is no longer needed.","message":"When using `logistro.getPipeLogger()` to capture subprocess output, it returns a pipe file descriptor. It is crucial to manually close this pipe using `os.close(pipe)` after the subprocess has completed to prevent resource leaks.","severity":"gotcha","affected_versions":"2.0.0+"}],"env_vars":null,"last_verified":"2026-04-09T00:00:00.000Z","next_check":"2026-07-08T00:00:00.000Z"}