decorator needs access to variables where it is used.
Chris Angelico
rosuav at gmail.com
Wed Oct 9 07:02:32 EDT 2019
On Wed, Oct 9, 2019 at 9:53 PM Antoon Pardon <antoon.pardon at vub.be> wrote:
>
> I have some logging utilities so that when I write library code, I just use the following.
>
> from logutil import Logger
>
> log = Logger(__name__)
Are you always absolutely consistent with this? Do you always have it
as a module-level variable and always called "log", and you never use
the name "log" for anything else? (Namespaced usage like "math.log" is
fine, but you never have a function-local "log" or anything.)
> And from then on I just use log, to do the logging of that module.
>
> But now I would like to write a decorator trace, so that a decorated
> function would log, its arguments and result.
>
> Something like:
>
> def trace(func):
>
> def wrapper(*args):
> log(DEBUG, "=> %s%s" % (func.__name__, args))
> result = func(*args)
> log(DEBUG, "%s => %s" (func.__name__, result))
>
> return wrapper
>
> The problem is that with this decorater, the log function
> used, will be the log function defined where the decorator
> is written and I would prefer it to use the log function
> where it is used, so that it uses the same log function
> as the function it decorates.
>
The decorator has full access to the function object, including a
reference to that function's module globals.
def trace(func):
log = func.__globals__["log"]
... proceed as before
As long as you can depend on "log" always being a module-level
(global) name, and not (for instance) a closure variable, this should
work. It's a bit ugly, but it should be fine since it's buried away in
the decorator.
ChrisA
More information about the Python-list
mailing list