Temporarily turn off warnings in PyROOT

Here is a simple context-manager class that you can use to temporarily raise the print level for a few commands:

import ROOT
class Quiet:
    """Context manager for silencing certain ROOT operations.  Usage:
    with Quiet(level = ROOT.kInfo+1):
       foo_that_makes_output

    You can set a higher or lower warning level to ignore different
    kinds of messages.  After the end of indentation, the level is set
    back to what it was previously.
    """
    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

I use it when saving canvases to suppress the “file created” message:

with MyROOT.Quiet():
  c1.SaveAs("somefile.pdf")

Here are some simple classes that play a similar role in C++. Where in Python you used a context manager and the “with” keyword, in C++ you just create a scope (with { and }) and instantiate a Quiet or Batch object. When the scope ends, the destructors return the ErrorIgnoreLevel and Batch status to what it was before.

// In a Utility.h file:
  class Quiet
  { // Usage:
    // { Quiet q(kWarning+1);
    //   StuffThatProducedOutput();
    // }
  public:
    Quiet(Int_t level = kInfo+1);
    ~Quiet();
  private:
    Int_t prev;
  };

  class Batch
  {
  public:
    Batch(Bool_t b = kTRUE);
    ~Batch();
  private:
    Bool_t prev;
  };
  
  // In a Utility.C file:
  Quiet::Quiet(Int_t level) : prev(gErrorIgnoreLevel) { gErrorIgnoreLevel = level;};
  Quiet::~Quiet() {gErrorIgnoreLevel = prev;};

  Batch::Batch(Bool_t b) : prev(gROOT->IsBatch()) { gROOT->SetBatch(b) ;};
  Batch::~Batch() { gROOT->SetBatch(prev) ;};

Hi Jean-François,

thanks for sharing these snippets.
Indeed RAII for C++ and context-managers for Python are indeed powerful tools/paradigms.

Cheers,
Danilo