Skip to content

Instantly share code, notes, and snippets.

@cgranade
Created August 13, 2013 02:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cgranade/6217348 to your computer and use it in GitHub Desktop.
Save cgranade/6217348 to your computer and use it in GitHub Desktop.
This module demonstrates a basic application of the Python Standard Library's logging module by using logging to implement a decorator that logs all calls to a function, method or property.
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
# log_calls.py: Decorator for logging calls to a function.
##
# © 2013 Christopher E. Granade (cgranade@gmail.com).
#
# Licensed under the AGPL version 3.
##
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
##
"""
This module demonstrates a basic application of the Python Standard Library's
`logging module`_ by using ``logging`` to implement a decorator that logs all
calls to a function, method or property.
.. logging module: http://docs.python.org/2/library/logging.html
"""
## IMPORTS ####################################################################
import functools
import logging
## DECORATORS #################################################################
def log_calls(name=None):
"""
Causes all calls to the decorated function to be logged.
"""
def decorator(fn):
_name = getattr(fn, '__name__', '<unnamed>') if name is None else name
logger = logging.getLogger(fn.__module__)
@functools.wraps(fn)
def logging_fn(*args, **kwargs):
logger.debug("{name}({args}{comma}{kwargs})".format(
name=_name,
args=", ".join(map(repr, args)),
comma=", " if kwargs else "",
kwargs=", ".join("{}={}".format(key, val) for key, val in kwargs.iteritems())
))
return fn(*args, **kwargs)
return logging_fn
return decorator
## DEMONSTRATION ##############################################################
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG)
class Example(object):
@log_calls()
def __init__(self, x):
self._x = x
@property
def x(self):
return self._x
@x.setter
@log_calls(name='x.setter')
def x(self, newval):
self._x = newval
@log_calls()
def print_x(self):
print self.x
ex = Example(3)
ex.x = 4
ex.print_x()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment