[IPython-dev] Configuring logging for the kernel?

Robert Kern robert.kern at gmail.com
Mon Feb 14 12:23:55 EST 2011


On 2/14/11 2:36 AM, Fernando Perez wrote:
> Howdy,
>
> I've merged:
>
> https://github.com/ipython/ipython/pull/264
>
> after Omar took Robert's feedback into account.  But I'm not very
> experienced with the logging module, so I'm wondering what the best
> pattern should be for enabling logging conveniently at the
> command-line level.  Right now, applications like the Qt console have
> to pass flags to the kernel (and there's some duplication there we
> should remove, like the code in ipythonqt.py and entry_point that
> creates the parsers).  We can pass a --log-level flag to the kernel
> entry point script easily, that's not a problem.
>
> My question has to do with how to cleanly and conveniently let the
> kernel log to the screen or a file, keeping in mind that the kernel
> will be running in a separate process.  The default approach to
> configuring logging for libraries is to let the application using a
> library set its own handlers, but in this case the app (say a Qt
> console) is calling the kernel in another process, so it can't pass it
> any handlers; in fact it can't pass the kernel anything other than
> command-line flags.
>
> The code path is somewhat elaborate, because options have to pass from
> the user-facing client through the kernel manager and ultimately to
> the actual kernel object (in ipkernel.py).  I admit I played with it
> for a while and got a bit lost, so I'm looking for some ideas on this
> one.  In addition, we need to keep in mind that all of the Qt console
> code is still in need of a Configurable restructuring, but that can be
> handled separately from this.

For now, just add command line arguments enough to use logging.basicConfig() in 
the kernel process, and don't worry about any more complicated logging 
scenarios. Just the filename/stream and level arguments are sufficient, I think. 
Untested, but probably sufficient:

   parser.add_argument('--log-file', default='stderr',
     help='The file to send logging information to [default: stderr]')
   parser.add_argument('--log-level', default='ERROR',
     choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
     help='The log level [default: ERROR]')

   args = parser.parse_args()
   kwds = {}
   do_logging = True
   if args.log_file.lower() == 'none':
     do_logging = False
   elif args.log_file == 'stdout':
     kwds['stream'] = sys.stdout
   elif args.log_file == 'stderr':
     kwds['stream'] = sys.stderr
   else:
     kwds['filename'] = args.log_file
   if do_logging:
     kwds['level'] = getattr(logging, args.log_level)
     logging.basicConfig(**kwds)
   else:
     root_logger = logging.getLogger()
     class NullHandler(logging.Handler):
       def emit(self, record):
         pass
     root_logger.addHandler(NullHandler())

The more general solution would be to make logging Configurable and allow the 
passing of a config file via the command line parameters.

-- 
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
  that is made terrible by our own mad attempt to interpret it as though it had
  an underlying truth."
   -- Umberto Eco




More information about the IPython-dev mailing list