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.) > 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 -- https://mail.python.org/mailman/listinfo/python-list