2

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?

Calimo
  • 7,510
  • 4
  • 39
  • 61
Sean Colby
  • 71
  • 2
  • And have you tried them? What was your output? The whole purpose of the Python VM is to wrap up the complexity so that you don't often have to worry about this. If the wrapper interface has been configured correctly by the designer, you should be able to pass a Python text stream. Otherwise, you would use the binary IO as described in the [documentation](https://docs.python.org/3/library/io.html). – Alan Jun 21 '18 at 23:12
  • Yes, tried both. Always returns the following error: `TypeError: in method 'OBMessageHandler_SetOutputStream', argument 2 of type 'std::ostream *'` – Sean Colby Jul 10 '18 at 17:58

1 Answers1

0

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
Calimo
  • 7,510
  • 4
  • 39
  • 61