Package: cs.logutils
Logging convenience routines.Latest release 20230212:
Late import of cs.upd at need to avoid import loop.The logging package is very useful, but a little painful to use.
This package provides low impact logging setup and some extremely
useful if unconventional context hooks for logging.The default logging verbosity output format has different defaults
based on whether an output log file is a tty
and whether the environment variable$DEBUGis set, and to what.On terminals warnings and errors get ANSI colouring.A mode is available that usescs.updfor certain log levels.Log messages dispatched viawarningand friends from this module
are automatically prefixed with the currentcs.pfxprefix string,
providing automatic message context.Some examples:Program initialisation:from cs.logutils import setup_logging

def main(argv):
    cmd = os.path.basename(argv.pop(0))
    setup_logging(cmd)Basic logging from anywhere:from cs.logutils import info, warning, error
[...]
def some_function(...):
    [...]
    error("nastiness found! bad value=%r", bad_value)Functionadd_logfile(filename, logger=None, mode='a', encoding=None, delay=False, format=None, no_prefix=False)Add aFileHandlerlogging to the specifiedfilename;
return the chosen logger and the new handler.Parameters:logger: if supplied and notNone, add theFileHandlerto thatLogger, otherwise to the root Logger. Ifloggeris a string, calllogging.getLogger(logger)to obtain the logger.mode,encodinganddelay: passed to theFileHandlerinitialiser.format: used to override the handler's default format.no_prefix: if true, do not put thePfxcontext onto the front of the message.Functioncritical(msg, *args, **kwargs)Emit a log atlogging.CRITICALlevel with the currentPfxprefix.FunctionD(msg, *args)Print formatted debug string straight tosys.stderrifD_modeis true, bypassing the logging modules entirely.
A quick'n'dirty debug tool.Functiondebug(msg, *args, **kwargs)Emit a log atlogging.DEBUGlevel with the currentPfxprefix.Functionerror(msg, *args, **kwargs)Emit a log atlogging.ERRORlevel with the currentPfxprefix.Functionexception(msg, *args, **kwargs)Emit an exception log with the currentPfxprefix.Functionftrace(func)Decorator to trace a function if__module__.DEBUGis true.Functionifdebug()Test theloginfo.levelagainstlogging.DEBUG.Functionifverbose(is_verbose, msg, *args, **kwargs)Conditionally log a message.Ifis_verboseisNone, log atVERBOSElevel and rely on the logging setup.
Otherwise, ifis_verboseis true, log atINFOlevel.Functioninfer_logging_level(env_debug=None, environ=None, verbose=None)Infer a logging level from theenv_debug, which by default
comes from the environment variable$DEBUG.Usually default tologging.WARNING, but ifsys.stderris a terminal,
default tologging.INFO.Parse the environment variable$DEBUGas a comma separated
list of flags.Examine the in sequence flags to affect the logging level:numeric < 1:logging.WARNINGnumeric >= 1 and < 2:logging.INFOnumeric >= 2:logging.DEBUG"DEBUG":logging.DEBUG"STATUS":STATUS"INFO":logging.INFO"TRACK":TRACK"WARNING":logging.WARNING"ERROR":logging.ERRORReturn an object with the following attributes:.level: A logging level..flags: All the words from$DEBUGas separated by commas and uppercased..module_names: Module names to be debugged..function_names: Functions to be traced in the formmodule_name.func_name.Functioninfo(msg, *args, **kwargs)Emit a log atlogging.INFOlevel with the currentPfxprefix.Functionlog(level, msg, *args, **kwargs)Emit a log at the specified level with the currentPfxprefix.FunctionlogException(exc_type, exc_value, exc_tb)Replacement forsys.excepthookthat reports via thecs.logutilslogging wrappers.ClassLogTimeLogTime is a context manager that logs the elapsed time of the enclosed
code. After the run, the field .elapsed contains the elapsed time in
seconds.MethodLogTime.__init__(self, tag, *args, **kwargs):
Set up a LogTime.Parameters:tag: label included at the start of the log entryargs: optional array; if not emptyargsis applied totagwith%level: keyword argument specifying a log level for a
default log entry, defaultlogging.INFOthreshold: keyword argument specifying minimum time to
cause a log, default None (no minimum)warning_level: keyword argument specifying the log level
for a warning log entry, defaultlogging.WARNINGwarning_threshold: keyword argument specifying a time
which raises the log level towarning_levelFunctionlogTo(filename, logger=None, mode='a', encoding=None, delay=False, format=None, no_prefix=False)Add aFileHandlerlogging to the specifiedfilename;
return the chosen logger and the new handler.Parameters:logger: if supplied and notNone, add theFileHandlerto thatLogger, otherwise to the root Logger. Ifloggeris a string, calllogging.getLogger(logger)to obtain the logger.mode,encodinganddelay: passed to theFileHandlerinitialiser.format: used to override the handler's default format.no_prefix: if true, do not put thePfxcontext onto the front of the message.ClassNullHandler(logging.Handler, logging.Filterer)AHandlerwhich discards its requests.ClassPfxFormatter(logging.Formatter)A Formatter subclass that has access to the program'scmdandPfxstate.MethodPfxFormatter.__init__(self, fmt=None, datefmt=None, cmd=None):
Initialise thePfxFormatter.Parameters:fmt: format template,
default fromDEFAULT_PFX_FORMAT'%(asctime)s %(levelname)s %(pfx)s: %(message)s'.
Passed through toFormatter.__init__.datefmt:
Passed through toFormatter.__init__.cmd: the "command prefix" made available to format strings.
If not set,cs.pfx.cmdis presented.Functionquiet(msg, *args, **kwargs)Emit a log atQUIETlevel with the currentPfxprefix.Functionsetup_logging(cmd_name=None, main_log=None, format=None, level=None, flags=None, upd_mode=None, ansi_mode=None, trace_mode=None, module_names=None, function_names=None, verbose=None, supplant_root_logger=False)Arrange basic logging setup for conventional UNIX command
line error messaging; return an object with informative attributes.
That object is also available as the globalcs.logutils.loginfo.Amongst other things, the default logger now includes
thecs.pfxprefix in the message.This function runs in two modes:if logging has not been set up, it sets up a root loggerif the root logger already has handlers,
monkey patch the first handler's formatter to prefix thecs.pfxstateParameters:cmd_name: program name, default frombasename(sys.argv[0]).
Side-effect: setscs.pfx.cmdto this value.main_log: default logging system.
IfNone, the main log will go tosys.stderr;
ifmain_logis a string, is it used as a filename to
open in append mode;
otherwise main_log should be a stream suitable
for use withlogging.StreamHandler().
The resulting log handler is added to theloggingroot logger.format: the message format formain_log.
IfNone, useDEFAULT_PFX_FORMAT_TTYwhenmain_logis a tty or FIFO,
otherwiseDEFAULT_PFX_FORMAT.level:main_loglogging level.
IfNone, infer a level from the environment
usinginfer_logging_level().flags: a string containing debugging flags separated by commas.
IfNone, infer the flags from the environment usinginfer_logging_level().
The following flags have meaning:D: set cs.logutils.D_mode to True;TDUMP: attach a signal handler to SIGHUP to do a thread stack dump;TRACE: enable various noisy tracing facilities;UPD,NOUPD: set the default forupd_modeto True or False respectively.upd_mode: a Boolean to activate cs.upd as themain_logmethod;
ifNone, set it toTrueifflagscontains 'UPD',
otherwise toFalseifflagscontains 'NOUPD',
otherwise set it frommain_log.isatty().
A true value causes the root logger to usecs.updfor logging.ansi_mode: ifNone,
set it frommain_log.isatty() and not cs.colourise.env_no_color(),
which thus honours the$NO_COLORenvironment variable
(seehttps://no-color.org/for the convention).
A true value causes the root logger to colour certain logging levels
using ANSI terminal sequences (currently only ifcs.updis used).trace_mode: ifNone, set it according to the presence of
'TRACE' in flags. Otherwise iftrace_modeis true, set the
globalloginfo.trace_leveltologinfo.level; otherwise it defaults
tologging.DEBUG.verbose: ifNone, then if stderr is a tty then the log
level isINFOotherwiseWARNING. Otherwise, ifverboseis
true then the log level isINFOotherwiseWARNING.Functionstatus(msg, *args, **kwargs)Emit a log atSTATUSlevel with the currentPfxprefix.Functiontrace(msg, *args, **kwargs)Emit a log message atloginfo.trace_levelwith the currentPfxprefix.Functiontrack(msg, *args, **kwargs)Emit a log atTRACKlevel with the currentPfxprefix.Functionupd(msg, *args, **kwargs)If we're using anUpdHandler,
update the status line otherwise write an info message.Note that this callsUpd.outdirectly withmsg%argsand thus does not include the currentPfxprefix.
You may well want to use thestatus()function instead.ClassUpdHandler(logging.StreamHandler, logging.Handler, logging.Filterer)AStreamHandlersubclass whose.emitmethod
uses acs.upd.Updfor transcription.MethodUpdHandler.__init__(self, strm=None, upd_level=None, ansi_mode=None, over_handler=None):
Initialise theUpdHandler.Parameters:strm: the output stream, defaultsys.stderr.upd_level: the magic logging level which updates the status line
viaUpd. Default:STATUS.ansi_mode: ifNone, set fromstrm.isatty().
A true value causes the handler to colour certain logging levels
using ANSI terminal sequences.Functionverbose(msg, *args, **kwargs)Emit a log atVERBOSElevel with the currentPfxprefix.Functionwarning(msg, *args, **kwargs)Emit a log atlogging.WARNINGlevel with the currentPfxprefix.Functionwith_log(filename, **kw)Context manager to add aLoggerto the output logs temporarily.Release LogRelease 20230212:
Late import of cs.upd at need to avoid import loop.Release 20220531:
PfxFormatter.patch_formatter: notice if record.args is not a tuple and do not try to prefix it (for now).Release 20220530:New QUIET log level between TRACK and STATUS, add new quiet() logging call.PfxFormatter.patch_formatter: bugfix handling of record.msg,record.args.Release 20220315:
A bit of a hack to prevent double patching a formatter, as when BaseCommand calls a BaseCommand and other circumstances where setup_logging() gets called more than once.Release 20220227:PfxFormatter: new patch_formatter() static method to modify an existing Formatter.setup_logging: just use PfxFormatter.patch_formatter on the first handler's formatter if logging is already set up.Release 20211208:
Docstring update.Release 20210721:
UpdHandler.emit: for newline-emitting messages, fall back to new .over_handler if the Upd is disabled.Release 20210718:
setup_logging: new supplant_root_logger=False parameter to pop the existing handler, typical use supplant_root_logger=sys.stderr.isatty().Release 20210306:Default logging level for ttys is now INFO, not STATUS.New VERBOSE level below INFO but above DEBUG.infer_logging_level: if verbose unspecified, logging=WARNING on a tty and TRACK otherwise, else if verbose, level=VERBOSE, otherwise WARNING.Include .verbose in the loginfo.New verbose() and ifverbose().Release 20201021:setup_logging: always provide loginfo.upd, being either main_handler.upd if upd_mode otherwise Upd().exception(): plumb keyword arguments.Release 20200729:
setup_logging: honour $NO_COLOR if ansi_mode not specified, perhttps://no-color.org/Release 20200613:LogTime: set .end on exit.UpdHandle.emit: fix message colouring logic.Release 20200521:
setup_logging: include the logger in loginfo (presently always the root logger).Release 20200519:
bugfix setup_logging: apparently a LoggingProxy does not have an encodingRelease 20200518:Sweeping removal of cs.obj.O, universally supplanted by types.SimpleNamespace.Default to logging level TRACK if stderr is a tty instead of logging.INFO.New ifverbose function with leadingverboseparameter: if None, log at INFO otherwise if true, log at TRACK, otherwise do not log.BREAKING: remove global logging_level and trace_level variables, put it all in the global loginfo.Make STATUS just below TRACK so that it is above INFO instead of below.New status() function for cs.upd messages.UpdHandler: treat status_level as special, going directly to Upd.out.Improved source line recitation on modern Python.Default level if sys.stderr.isatty() now STATUS, not TRACK.Some fixes for loginfo initialisation and setting cs.pfx.cmd.Release 20200229:Update for new Upd.without context manager.setup_logging: defaultupd_modetomain_log.isatty(), was previously False.Drop UpdHandler.upd method, shadowed by instance attribute, never used.Release 20190923:NewTRACKconstant equal tologging.INFO+5to provide a level higher thanINFO(which seems unreasonably noisy) and lower thanWARNINGwarning for tracking salient events.Newtrack()function to match.Release 20190220:
Improvements to upd_mode.Release 20190103:
Documentation updates.Release 20190101:
Bugfix for @contextmanager usage.Release 20171030:
Assorted fixes from recent module reshuffle. Other small features and cleanups. Drop a couple of unused functions.Release 20160828:
Use "install_requires" instead of "requires" in DISTINFO.Release 20160827:Pfx: importexithandlerPreliminary per-module and per-function syntax accepted in $DEBUG envvar.Improvements to X(), add DP() and XP() prefixed flavours.status() function to update terminal status line.New X_via_tty global flag: directs X() to tty instead of sys.stderr.Assorted other minor improvements.Release 20150118:
metadata updatesRelease 20150110:
Initial PyPI release.