import logging logging.getLogger('foo').addHandler(logging .NullHandler()) should have the desired effect. If an organisation produces a number of libraries, then the logger name specified can be ‘orgname.foo’ rather than just ‘foo’. Note: It is strongly advised that you do not add any handlers other than$_{NullHandler}$to your library’s loggers . This is because the configuration of handlers is the prerogative of the application developer who uses your library. The application developer knows their target audience and what handlers are most appropriate for their application: if you add handlers ‘under the hood’, you might well interfere with their ability to carry out unit tests and deliver logs which suit their requirements. The numeric values of logging levels are given in the following table. These are primarily of interest if you want to define your own levels, and need them to have specific values relative to the predefined levels. If you define a level with the same numeric value, it overwrites the predefined value; the predefined name is lost. 3 Logging Levels Level Numeric value CRITICAL 50 ERROR 40 WARNING 30 INFO 20 DEBUG 10 NOTSET 0 Levels can also be associated with loggers, being set either by the developer or through loading a saved logging configuration. When a logging method is called on a logger, the logger compares its own level with the level associated with the method call. If the logger’s level is higher than the method call’s, no logging message is actually generated. This is the basic mechanism controlling the verbosity of logging output. Logging messages are encoded as instances of the$_{LogRecord}$ class. When a logger decides to actually log an event, a$_{LogRecord}$ instance is created from the logging message. Logging messages are subjected to a dispatch mechanism through the use of handlers , which are instances of sub- classes of the $_{Handler}$class. Handlers are responsible for ensuring that a logged message (in the form of a $_{LogRecord}$) ends up in a particular location (or set of locations) which is useful for the target audience for that mes- sage (such as end users, support desk staff, system administrators, developers). Handlers are passed$_{LogRecord}$ instances intended for particular destinations. Each logger can have zero, one or more handlers associated with it (via the addHandler() method of $_{Logger}$). In addition to any handlers directly associated with a logger, all handlers associated with all ancestors of the logger are called to dispatch the message (unless the propagate flag for a logger is set to a false value, at which point the passing to ancestor handlers stops). Just as for loggers, handlers can have levels associated with them. A handler’s level acts as a filter in the same way as a logger’s level does. If a handler decides to actually dispatch an event, the$_{emit()}$ method is used to send the message to its destination. Most user-defined subclasses of$_{Handler}$will need to override this$_{emit()}$ . 13