3

I'm importing a module foo which uses Python's logging module. However, foo produces a huge amount of logging output, and I need to use stdout to communicate important information to the user, which is largely being drowned out by the ridiculous output of the module I'm importing.

How can I disable the module's ability to log to stdout without modifying foo's code? I still want it to log to the files it logs to, but I don't want it logging to stdout.

I have tried the following:

logging.getLogger("foo").propagate = False

and

@contextlib.contextmanager
def nostdout():
    class DummyFile(object):
        def write(self, x): pass
    save_stdout = sys.stdout
    sys.stdout = DummyFile()
    yield
    sys.stdout = save_stdout

with nostdout(): import foo
Alex Alifimoff
  • 1,850
  • 2
  • 17
  • 34
  • 1
    Does module `foo` configure the logging itself? If it is a library it should not. Then you can simply configure logging to go to a file instead of stdout. https://docs.python.org/3/library/logging.config.html#module-logging.config – dsh Jan 29 '16 at 16:08
  • It is a library. Sadly all libraries are not well-written, and this one does configure the logging itself. – Alex Alifimoff Jan 29 '16 at 16:09

2 Answers2

2

Try the following:

logging.getLogger(<logger_name_used_in_foo>).propagate = False
MaxU - stand with Ukraine
  • 205,989
  • 36
  • 386
  • 419
0

I'm referencing this article. In general, if you want to capture anything written to stdout you can use the contextlib in Python 3:

from contextlib import redirect_stdout

f = io.StringIO()
with redirect_stdout(f):
    print('foobar')
    call_annoying_module()
print('Stdout: "{0}"'.format(f.getvalue()))

On Python 3.4 and older, redirect_stdout can be implemented like this:

from contextlib import contextmanager

@contextmanager
def stdout_redirector(stream):
    old_stdout = sys.stdout
    sys.stdout = stream
    try:
        yield
    finally:
        sys.stdout = old_stdout

If the library has any C bindings that print using puts then it gets more complicated. See the article.

The easiest case is when you're running another program using subprocess, then all stdout output can be easily captured.

proc = subprocess.Popen("echo output".split(), stdout=subprocess.PIPE)
std_output, err_output = proc.communicate()
Hugo O. Rivera
  • 651
  • 4
  • 11
  • I'll give this a shot, but a previous user posted something similar to this (using a context manager and manually redirecting stdout to a dummy file), but that didn't work. – Alex Alifimoff Jan 29 '16 at 16:38
  • I see. If all else fails and if it's possible to call the module as a separate program, see my recent edit at the bottom of the post. – Hugo O. Rivera Jan 29 '16 at 16:40
  • Oh, sorry, using Python2.7 so this doesn't work generally. – Alex Alifimoff Jan 29 '16 at 16:42
  • I'm not entirely sure how your subprocess example works. I need to be able to use objects from the module I'm importing. – Alex Alifimoff Jan 29 '16 at 16:42
  • Ok, nevermind the subprocess example. On Python 2 you can implement redirect_stdout on your own. See edits. – Hugo O. Rivera Jan 29 '16 at 16:48
  • I did that -- that's the solution I was referencing that didn't work. – Alex Alifimoff Jan 29 '16 at 16:48
  • Specifically it was `def nostdout(): save_stdout = sys.stdout; sys.stdout = DummyFile(); yield; sys.stdout = save_stdout` with DummyFile() being a class that implemented an empty `write` method. – Alex Alifimoff Jan 29 '16 at 16:49
  • Obviously with a `@contextlib.contextmanager` flag... I'll add this to the OP so this is clear. – Alex Alifimoff Jan 29 '16 at 16:50
  • I see. You can also try to do it without decorators by reassigning stdout as needed. See [this answer](http://stackoverflow.com/questions/22822267/python-capture-print-output-of-another-module) – Hugo O. Rivera Jan 29 '16 at 16:51
  • It's a proprietary library. I have the source code. Based on your last comment, I logged stdout to file. Interestingly but perhaps unsurprisingly, it isn't outputting the text that I'm trying to get rid of, so somehow it is putting text to stdout without Python being aware of it. Unclear if that makes sense. – Alex Alifimoff Jan 29 '16 at 16:57
  • Basically it is outputting things to stdout that aren't outputted to a file when I redirect stdout to that file. – Alex Alifimoff Jan 29 '16 at 16:57
  • Even doing logging.shutdown() doesn't accomplish anything. – Alex Alifimoff Jan 29 '16 at 17:03
  • [Maybe use the pdb to detect when stdout is changed?](http://sourceforge.net/blog/watchpoints-in-python/) – Hugo O. Rivera Jan 29 '16 at 17:05
  • I'll try that when I get back the office. Honestly at this point I'm considering just patching the library myself since it's clearing doing something odd. – Alex Alifimoff Jan 29 '16 at 18:25