python - Decorator to log function execution line by line -


i'm working on script takes few minutes run, , provide output user progress. unfortunately i'm exceedingly lazy. i'd write function without logging, , apply decorator steps through function , prints each line before executing line. i'm looking loggingdecorator such that:

>>> @loggingdecorator ... def myfunction(): ...     foo() ...     bar() ...     baz() >>> myfunction() starting myfunction foo() ... [ok] bar() ... [ok] baz() ... [ok] myfunction done! 

here's i've tried far:

import sys   def logging_tracer(frame, event, arg):     def local_tracer(local_frame, event, arg):         if frame local_frame:             print frame.f_code.co_name, event, arg      print frame.f_code.co_name, event, arg     return local_tracer   def loggingdecorator(func):     def _wrapper():         old_trace_function = sys.gettrace()         sys.settrace(logging_tracer)         try:             result = func()         except:             raise         else:             return result         finally:             sys.settrace(old_trace_function)     return _wrapper 

unfortunately, prints bit much; follows function calls , prints them out, line line (well, doesn't print source line, existing answers using inspect, combined stuff on frame object in trace function it), i'm bit stumped how logging_tracer unless function in question decorated.

so here's came with. @corley brigman's comment got me started in right direction. bit hackey, sys.gettrace/settrace rather promenently documented "cpython implementation details", , solution should not expected work in other implementations. said, seems work out pretty well. tracing functionality in cpython not provide notification of "line finished executing", [ok] question doesn't make sense.

fixing recursive tracing issue simple matter of keeping cache of functions decorated, , produce output if frame being traced function decorated.

import inspect import sys   def logging_tracer(frame, event, arg):     lines, firstline = inspect.getsourcelines(frame)      def local_tracer(local_frame, event, arg):         if event == 'line' , frame local_frame:             print event, frame.f_lineno,'\t', lines[frame.f_lineno - firstline]             #print event, lines[frame.f_lineno - firstline]             #print frame.f_code.co_name, frame.f_lineno, event, arg      if frame.f_code in log_these_functions:         print event, frame.f_lineno,'\t', lines[frame.f_lineno - firstline + (event == 'call')]         #print frame.f_code.co_name, event, arg         return local_tracer     else:         return none   log_these_functions = set()   def loggingdecorator(func):     log_these_functions.add(func.func_code)      def _wrapper():         old_trace_function = sys.gettrace()         sys.settrace(logging_tracer)         try:             result = func()         except:             raise         else:             return result         finally:             sys.settrace(old_trace_function)     return _wrapper 

Comments

Popular posts from this blog

java.util.scanner - How to read and add only numbers to array from a text file -

rewrite - Trouble with Wordpress multiple custom querystrings -