Redirect logs to file in Pybel?

152 views Asked by At

Similar to this post, but rather than change the logging level, I would like to redirect all logging information to a file. I believe the relevant API call is:

pybel.ob.obErrorLog.SetOutputStream()

or:

pybel.ob.OBMessageHandler().SetOutputStream()

But the SetOutputStream() method only accepts objects of type std::ostream *, not Python file streams, e.g. open('/path/to/log.txt', 'w') or sys.stdout.

Here are a few things I tried:

from openbabel import openbabel
import io
import sys

obHandler = openbabel.OBMessageHandler()
obHandler.SetOutputStream(io.BytesIO())
##Out: TypeError: in method 'OBMessageHandler_SetOutputStream', argument 2 of type 'std::ostream *'

obHandler.SetOutputStream(sys.stderr)
##Out: TypeError: in method 'OBMessageHandler_SetOutputStream', argument 2 of type 'std::ostream *'

with open("test.out", "w") as fd:
    obHandler.SetOutputStream(fd)
##Out: TypeError: in method 'OBMessageHandler_SetOutputStream', argument 2 of type 'std::ostream *'

TL;DR: is there a reasonable way to direct log information to a file in PyBel?

1

There are 1 answers

0
Calimo On

One way work around this error is to capture the standard error stream.

Unfortunately one cannot directly redirect the standard error to an IOStream, as OpenBabel is operating on the underlying C standard error and unaware of the Python one.

But, thanks to this Stack Overflow answer, it is actually possible to capture the underlying error stream to a string.

With the OutputGrabber class loaded/imported, you can capture the output as so:

import sys
from openbabel import openbabel
obConversion = openbabel.OBConversion()
obConversion.SetInFormat("sdf")
mol = openbabel.OBMol()

out = OutputGrabber(sys.stderr)
with out:
    success = obConversion.ReadString(mol, "INVALID\n\n")

And the text is now in out.capturedtext:

print(out.capturedtext)
==============================
*** Open Babel Warning  in ReadMolecule
  WARNING: Problems reading a MDL file
Cannot read comment line