Django management commands expose a verbosity flag (-v, --verbosity with values {0,1,2,3}) by default (implemented in the BaseCommand class), but this flag has no effect unless the developer of the command has cared to do so.
E.g. When using default Python logging in management commands (or third-party libraries used in a command), logging adheres to the settings in Django’s settings.LOGGING dict. To me it seems intuitive that a management command called with -v 3 will switch (for the output of that command) the log level to logging.DEBUG, but it doesn’t.
I would like to propose a default implementation in Django’s BaseCommand, aiding developers to handle verbosity control with minimal effort.
My observations:
- Django exposes a default interface for verbosity control in management commands, implying to the end user that this does something useful. The fact that this flag is always available raises end-user expectation.
- The implementation of verbosity is left to the developer, but no guidelines or hints are given. The documentation doesn’t spend a single word on logging or verbosity.
- The opaque descriptions of the verbosity levels in the management command flag (
Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output) don’t map naturally to existing standards like Python’s builtinlogginglog levels. This raises the bar for developers to do something useful with the flag. - Willing developers of management commands in third-party apps might implement verbosity control, but as no guideline, preferred approach or basic implementation is available, everyone has to re-invent the wheel somehow. This again raises the bar for developers to actually do this. All these implementations will vary wildly in their interpretation of how verbosity control is applied.
- Less willing (or ignorant) developers won’t implement any verbosity control at all. This happens a lot. The lack of guidance might be a reason for this.
As an end-user of (third-party) commands, the lack of verbosity control despite a CLI flag being available has annoyed me to no end.
As a willing developer of management commands, I find that I either need to look back to previous work for easy handling of the verbosity flag, or just think up something new each time. Over the years I might have created a dozen slightly different ways to handle this.
Thus I propose to create a default implementation for handling verbosity. My basic idea would be to implement in Django something like:
- Map
--verbosityvalues to Pythonlogginglevels (e.g. 0 →logging.ERROR, 3 →logging.DEBUG). - The
BaseCommandclass should automatically create alogginglogger that is easily usable from methods in the command, e.g.self.log.info(“foo”). This logger should adhere tosettings.LOGGING, but enforce the log level set in the–-verbosityflag. It could possibly also enforce output to stdout (without doubling up with existing configuration that sends to stdout?). - The application of the verbosity level to loggers could be configurable in code: only the logger local to the management command file, to the django app the command belongs to, or even the root logger.
- Promote use of the
self.logobject (or theloggingmodule) in Django documentation about custom management commands. - Maybe document (or even implement) a preferred way to combine the verbosity level with
Command.stdout.write().
Would this be any good? Other ideas and suggestions welcome of course.