Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python indentation \ context level to log prefix length

Tags:

My idea is to make a context logging scheme as showed on the example below:

[   DEBUG] Parsing dialogs files [   DEBUG] ... [DialogGroup_001] [   DEBUG] ...... Indexing dialog xml file [c:\001_dlg.xml] [   DEBUG] ......... dialog [LobbyA] [   DEBUG] ............ speech nodes [3] [   DEBUG] ............... [LobbyA_01] [   DEBUG] ............... [LobbyA_02] [   DEBUG] ............... [LobbyA_03] [   DEBUG] ............ sms nodes [0] [   DEBUG] ......... dialog [LobbyB] [   DEBUG] ............ speech nodes [3] [   DEBUG] ............... [LobbyB_01] [   DEBUG] ............... [LobbyB_02] [   DEBUG] ............... [LobbyB_03] [   DEBUG] ............ sms nodes [0] [   DEBUG] ... [DialogGroup_002] [   DEBUG] ...... Indexing dialog xml file [c:\002_dlg.xml] [   DEBUG] ......... dialog [HighGroundsA] [   DEBUG] ............ speech nodes [3] [   DEBUG] ............... [HighGroundsA_01] [   DEBUG] ............... [HighGroundsA_02] [   DEBUG] ............... [HighGroundsA_03] [   DEBUG] ............ sms nodes [0] 

At this point, I'm using Python's logging module with custom, hand-written prefixes when logging, for example:

(...)  log.debug('') log.debug('Parsing dialogs files') for dlg in defDlgList:     log.debug('... [{0}]'.format(dlg))  (...) 

It's working quite ok, but there are some subtle problems, for example: when logging from inside functions - they may be called from various scopes and prefix length may vary for each call.

I'm looking for an elegant and invisible way to establish a length of a '...' prefix automatically for each log. I'd rather avoid passing prefix length as a parameter to each function or setting the length using explicit calls, for example:

(...)  logWrapper.debug('') logWrapper.debug('Parsing dialogs files') for dlg in defDlgList:     logWrapper.nextLogLevelBegin()     logWrapper.debug('[{0}]'.format(dlg))     logWrapper.nextLogLevelEnd()  (...) 

Is there a way to get the current indentation level from Python's parser or construct a scope sensitive wrapper class for logging?

like image 964
Helbreder Avatar asked Mar 31 '11 11:03

Helbreder


People also ask

What are the five levels of logging in Python?

In Python, the built-in logging module can be used to log events. Log messages can have 5 levels - DEBUG, INGO, WARNING, ERROR and CRITICAL. They can also include traceback information for exceptions. Logs can be especially useful in case of errors to help identify their cause.

What is level in logging in Python?

Python Logging Levels There are six log levels in Python; each level is associated with an integer that indicates the log severity: NOTSET=0, DEBUG=10, INFO=20, WARN=30, ERROR=40, and CRITICAL=50. All the levels are rather straightforward (DEBUG < INFO < WARN ) except NOTSET, whose particularity will be addressed next.

What is the default log level in Python?

The default level is WARNING , which means that only events of this level and above will be tracked, unless the logging package is configured to do otherwise. Events that are tracked can be handled in different ways. The simplest way of handling tracked events is to print them to the console.

How do you indent a line in Python?

You can indent the lines in a string by just padding each one with proper number of pad characters. This can easily be done by using the textwrap. indent() function which was added to the module in Python 3.3.


2 Answers

Perhaps you can use inspect.getouterframes to find the indentation level:

import inspect import logging  logger=logging.getLogger(__name__)  def debug(msg):     frame,filename,line_number,function_name,lines,index=inspect.getouterframes(         inspect.currentframe())[1]     line=lines[0]     indentation_level=line.find(line.lstrip())     logger.debug('{i} [{m}]'.format(         i='.'*indentation_level,         m=msg                     ))  def foo():         debug('Hi Mom')     for i in range(1):         debug("Now we're cookin")  if __name__=='__main__':     logging.basicConfig(level=logging.DEBUG)     foo() 

yields

DEBUG:__main__:.... [Hi Mom] DEBUG:__main__:........ [Now we're cookin] 
like image 162
unutbu Avatar answered Nov 08 '22 04:11

unutbu


Searching through the docs, I don't really see a way to get current indentation level. The best you can do, is get the current function nesting level, like this:

len(traceback.extract_stack()); 

Example:

import traceback;  def test():     print len(traceback.extract_stack());   print len(traceback.extract_stack()); # prints 1 test(); # prints 2 
like image 23
Silver Light Avatar answered Nov 08 '22 02:11

Silver Light