util package

The util package: general-purpose building blocks for Python applications – persistence, attributes with inheritance, commands with undo and a command-line parser, the observer pattern, preferences, and some Tk widgets (a terminal, an attribute editor, dialogs, tooltips). It came out of Semantic Nets, but doesn’t depend on it.

This module sets up logging. Modules get their loggers with util.getLogger(__name__): an application can supply its own getLogger() in its top-level package, which is then used instead (see getLogger()), and set up the log file with setupLogger().

util._loggingSetUp: bool = False

Whether setupLogger() has been called (by the application, or by getLogger() for want of it).

class util.Logger(name, level=0)

Bases: Logger

A logging.Logger with a print() method too (see util.getLogger()).

print(*args, **kwargs)

Intended to mimic the print system command but allowing for redirection and multiple destinations if necessary.

Parameters:
  • args

  • kwargs

util.getLogger(name: str)

Create or find a Logger for name. This should be called as util.getLogger(__name__).

Parameters:

name (str)

Returns:

Return type:

util.setupLogger(loggerClass: type | None = None, logFileName: str | None = None)

Set up the logger to log to a log file and to stderr.

Parameters:
  • loggerClass (type(logging.Logger)|None) – A logging.Logger subtype to set the loggerClass to.

  • logFileName (str|None) – The name of the file to log to. By default it will be the stem (filename only) of current executable, and it will be in the current directory. If it doesn’t have a file extension, “.log” will be appended. A relative name is put in the user’s log folder instead (eg: ~/Library/Logs/<program>/: see util.platformSupport.logFolder()) when the program is packaged (eg: a .app) or the current directory can’t be written.

util._freshLogFile(logFileName: str) → str
Returns:

logFileName, emptied (the last run’s log is removed); or, if it can’t be removed because another copy of the program has it open (as on Windows, where an open file can’t be removed), the first of “<name>-2.log”, “<name>-3.log”, … that can.

class util.DynamicStderrHandler(*args: object, **kwargs: object)

Bases: StreamHandler

A StreamHandler that always writes to the CURRENT sys.stderr at emit time, rather than whatever sys.stderr was when this handler was constructed.

Useful when sys.stderr is reassigned later (e.g. redirected into a GUI terminal widget or a LoggerWriter) and you want log output to follow it.

__init__(*args: object, **kwargs: object) → None
Parameters:
  • args (object)

  • kwargs (object)

property stream: object

Always return the current sys.stderr, not a frozen reference.

Returns:

The live sys.stderr object.

Return type:

object

util._getTopLevelPackageName() → str | None

Determine the NAME of __main__’s top-level enclosing package, purely by inspecting sys.modules and walking the file system – this never imports anything as a side effect.

This used to also resolve (and, if necessary, import) the module object itself, but that’s exactly what caused a nasty bootstrapping hazard: this gets called (via getLogger()) from module-level code all over pythonUtils, e.g. util.persistence.serialize calls util.getLogger(__name__) while IT is still being imported, and if the app’s own top-level package (e.g. “sn”) is the thing needing pythonUtils to finish loading in the first place, forcing an import of “sn” right here re-enters that same still-in-progress import chain and blows up with a “partially initialized module” ImportError. Callers now do their own sys.modules.get(name) lookup (see getLogger()) so a not-yet-imported top-level package is simply reported as “not available yet” rather than force-imported.

Returns:

The top-level package’s name, or None if __main__ was run as a standalone script or from an interactive session with no enclosing package.

Return type:

str|None

util._getLogger(name: str) → Logger

Return a properly typed SNLogger for the molule who’s __name__ is given in name. This may be either created of just returned, depending on if it exists already.

Parameters:

name (str) – Always call this with the __name__ variable for the file.

Returns:

The properly typed SNLogger for created.

Return type:

SNLogger

Subpackages

Submodules