Riju Dasgupta
Riju Dasgupta

Reputation: 13

How can I redirect only part of a stream?

I'm using Python on bash on Linux. I would like to be able to suppress error messages from a particular module, but keep other error messages. An example would probably be the most efficient way to convey what I want:


File: module.py

import sys
sys.stderr.write('Undesired output.\n')

File: script.py

import module
import sys

sys.stderr.write('Desired output.\n')
sys.stdout.write('Desired output.\n')
x = int('a')

Output of running script.py:

$ python script.py
Undesired output.
Desired output.
Desired output.
Traceback (most recent call last):
  File "script.py", line 6, in <module>
    x = int('a')
ValueError: invalid literal for int() with base 10: 'a'

Desired output of running script.py:

$ python script.py
Desired output.
Desired output.
Traceback (most recent call last):
  File "script.py", line 6, in <module>
    x = int('a')
ValueError: invalid literal for int() with base 10: 'a'

I cannot modify module.py, but I must use it. I've tried all kinds of redirects, and opening new file descriptors, but I can't seem to change the file descriptors of the calling shell from within python, so

$ python script.py 2>/dev/null
Desired output.

kills ALL stderr output. Since I know that the module is causing the undesired message, I know exactly which point I want to stop redirecting stderr to /dev/null and start redirecting it to &1, but I can't seem to be able to do it from within Python.

Any advice is much appreciated!

Upvotes: 0

Views: 117

Answers (2)

Riju Dasgupta
Riju Dasgupta

Reputation: 13

akubot's answer and some experimentation led me to the answer to this question, so I'm going to accept it.

Do this:

$ exec 3>&1

Then change script.py to be the following:

import sys, os
sys.stderr = open(os.devnull, 'w')
import module
sys.stderr = os.fdopen(3, 'w')

sys.stderr.write('Desired output.\n')
sys.stdout.write('Desired output.\n')
x = int('a')

Then run like this:

$ python script.py 2>/dev/null

yielding the desired output.

Upvotes: 1

akubot
akubot

Reputation: 131

There is an example here in the accepted answer that might help you

Temporarily Redirect stdout/stderr

but in your case, it assumes that you could do

import module

after

import sys

and after you've redirected stderr in your Python code. Like

import sys

... redirect code here

import module

... code to remove redirect

Don't know if that will break your desired functionality, beyond the redirects.

Also you're not supposed to stick import statements in the middle of your code, as it violates the PEP8 style guide.

Upvotes: 1

Related Questions