Skip to content

Latest commit

 

History

6 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pyutils

Shared Python library with logging and configuration utilities.

Installation

pip install git+https://github.com/RomLecat/pyutils.git

Usage

Log

Setup for the standard logging module. setup_logging attaches one handler to the root logger and returns a named logger. All named loggers propagate their records to that handler. You can call setup_logging more than one time. Only the first call configures the handler.

from pyutils import Log

logger = Log.setup_logging('myapp')
logger.info('Info message')
logger.warning('Warning')
logger.error('Error')

Levels

The library adds a TRACE level below DEBUG:

logger.trace('Very detailed message')

Set the level at runtime:

Log.set_level('TRACE')   # a level name or the matching integer
Log.enable_debug()       # shortcut for the DEBUG level

set_level and enable_debug change the root logger only. A level that silence puts on a named logger stays in place.

Noisy and framework loggers

Log.silence('urllib3')          # WARNING and above only
Log.capture('worker.engine')    # remove a foreign handler, propagate again

Use capture on a framework that attaches its own handler. The records then go to the root handler with the same format as the rest. capture also removes the level of the logger: the logger then follows the root level.

Configuration

Variable Values Default
LOG_LEVEL TRACE, DEBUG, INFO, WARNING, ERROR, CRITICAL INFO
DEBUG true, 1, t unset
LOG_FORMAT json, console console on a terminal, else json

LOG_LEVEL has priority over DEBUG. The values are case insensitive. An invalid LOG_LEVEL is ignored.

Output formats

The json format writes one JSON object per line on stdout. A log collector reads the severity from the level field. A traceback stays on the same line.

{"timestamp":"2026-01-01T12:00:00.000Z","level":"ERROR","logger":"worker","message":"Task failed","exception":"Traceback..."}

Fields sent through extra are added to the object:

logger.info('Task done', extra={'task_id': 42})

The formatter keeps these field names for itself: timestamp, level, logger, message, exception and stack. An extra field with one of these names does not go into the output. Choose another name.

The output is ASCII: the formatter writes other characters as \uXXXX escapes. A field that JSON cannot write, such as a circular container, goes into the output through repr(). The record is never lost.

The console format writes a human readable line. It adds colors only on a terminal:

2026-01-01T12:00:00.000 WARNING  [worker] Disk is almost full

Both formats write the time in UTC.

Level Color
TRACE Grey
DEBUG Grey
INFO Plain
WARNING Yellow
ERROR Red
CRITICAL Bold red

Config

Configuration manager built on Dynaconf, with scope support and environment variable overrides.

from pyutils import Config

config = Config("custom_scope")
db_url = config.get("url")
paths = config.get_paths("directory")

Configuration file

By default, Config loads config.yml from the working directory. This path can be overridden via the CONFIG_FILE environment variable.

Example config.yml:

global:
  debug: false
  dry_run: false

my_class:
  foo: bar

Value resolution

Values are resolved in the following priority order:

  1. Environment variable SCOPE_PARAM (e.g. DATABASE_URL)
  2. Environment variable PARAM (e.g. URL)
  3. Scoped key in config file (e.g. my_class.foo)
  4. Key under the global scope in config file
  5. Default value (if provided), otherwise KeyError

Global flags

config.dry_run  # reads DRY_RUN, returns a boolean
config.debug    # reads DEBUG, returns a boolean

Dependencies

About

Collection of Python utilities shared across my projects

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages