On 9/10/19 13:02, Chris Angelico wrote: > On Wed, Oct 9, 2019 at 9:53 PM Antoon Pardon <antoon.par...@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.)
I have been up to now, but I will take this under consideration when thinking about how to proceed. >> 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. Nice idea, I can work with that. Antoon. -- https://mail.python.org/mailman/listinfo/python-list