How can I log a functions arguments in a reusable way in Python?
Question: I've found myself writing code like this several times:

    
    
    def my_func(a, b, *args, **kwargs):
        saved_args = locals() # Learned about this from http://stackoverflow.com/a/3137022/2829764
        local_var = "This is some other local var that I don't want to log"
        try:
            a/b
        except Exception as e:
            logging.exception("Oh no! My args were: " + str(saved_args))
            raise
    

Running `my_func(1, 0, "spam", "ham", my_kwarg="eggs")` gives this output on
stderr:

    
    
    ERROR:root:Oh no! My args were: {'a': 1, 'args': (u'spam', u'ham'), 'b': 0, 'kwargs': {'my_kwarg': u'eggs'}}
    Traceback (most recent call last):
      File "/Users/kuzzooroo/Desktop/question.py", line 17, in my_func
        a/b
    ZeroDivisionError: division by zero
    

My question is, can I write something reusable so that I don't have to save
locals() at the top of the function? And can it be done in a nice Pythonic
way?

EDIT: one more request in response to @mtik00: ideally I'd like some way to
access saved_args or the like from within my_func so that I can do something
other than log uncaught exceptions (maybe I want to catch the exception in
my_func, log an error, and keep going).


Answer: **Decorators** are what you are looking for. Here's an example:

    
    
    import logging
    from functools import wraps
    
    
    def arg_logger(func):
    
        @wraps(func)
        def new_func(*args, **kwargs):
            saved_args = locals()
            try:
                return func(*args, **kwargs)
            except:
                logging.exception("Oh no! My args were: " + str(saved_args))
                raise
    
        return new_func
    
    
    @arg_logger
    def func(arg1, arg2):
        return 1 / 0
    
    if __name__ == '__main__':
        func(1, 2)
    

Here, I'm using arg_logger() as a _decorator_. Apply the decorator to any
function you want to have this new behavior.

There's a good discussion about decorators
[here](http://en.wikipedia.org/wiki/Python_syntax_and_semantics#Decorators).

