Decorator for Quiet Functions & Methods

Hi, I’m frequently annoyed by various TObject::Info messages and such (especially those about saving a file or overwriting a canvas), so I tried to implement a simple way of temporarily silencing such messages without globally turning off all messages.

My solution uses a python decorator, so the new “quiet” call looks similar enough to the original call that you could imagine using sed or search-and-replace to turn a bunch of TCanvas::SaveAs calls into quieted ones:

>>> c1.SaveAs("myfile.pdf")
Info in <TCanvas::Print>: pdf file myfile.pdf has been created
>>> Quiet(c1.SaveAs)("myfile.pdf") # No message printed

Here is the decorator, it’s actually quite simple:

def Quiet(func,level = ROOT.kInfo + 1):
    def qfunc(*args,**kwargs):
        oldlevel = ROOT.gErrorIgnoreLevel
        ROOT.gErrorIgnoreLevel = level
        try:
            return func(*args,**kwargs)
        finally:
            ROOT.gErrorIgnoreLevel = oldlevel
    return qfunc

It has a default “quiet” value of ROOT.kInfo+1 so that it suppressed everything less-than-or-equal-to Info messages in urgency. The optional second parameter to the decorator can be used to replace that with kWarning, kError, or whatever you like:

>>> to = ROOT.TObject()
>>> Quiet(to.Warning,ROOT.kError)("foo","bar") # No message
>>> Quiet(to.Error,ROOT.kError)("foo","bar") # Prints the message, since the level is the lowest-priority that is printed.

I am hoping for a PyROOT expert to comment on my decorator to assure me that it won’t break anything. Especially I am wondering if I got the try/finally correct so that if func(*arg,**kwargs) has a problem, that the error level goes back to normal. I also figured other people might find this useful.

Jean-François

Jean-François,

should be fine in the face of exceptions. You may also like:[code]class Quiet:
def init(self, level = ROOT.kInfo + 1):
self.level = level

def enter(self):
self.oldlevel = ROOT.gErrorIgnoreLevel
ROOT.gErrorIgnoreLevel = self.level

def exit(self, type, value, traceback):
ROOT.gErrorIgnoreLevel = self.oldlevel[/code]which can be used like this:with Quiet(ROOT.kError): c1.SaveAs("myfile.pdf")and the advantages being readability, and scoping a whole block of calls if so desired.

Also wanted to add that the rootpy logger can selective tune out messages from specific contexts. See http://www.rootpy.org/modules/logger.html#capturing-root-messages-with-rootpy-logger.

HTH,
Wim