user3058846
user3058846

Reputation:

Reading from sys.stderr in python

There are countless amount of questions here about how to read from stderr and stdout of a subprocess. Is it possible to do so with the current process's stderr? I checked it and it raised an IO Error : File not open for reading.

I needed to read the stderr and get the data for further processing. Are there any ways to open the file in 'r+' mode?

One way I thought of was to override the default sys.stderr with a class like:

class CustomStdErr(object):
    def write(self, data):
        with open(fakestderr, 'r+') as f:
            f.write(data)

sys.stderr = CustomStdErr()

Are there any other ways to do it more directly?

EDIT: Why I need the stderr:
There is a thread (call it X) in the code that interacts with the main thread (call it M). The main thread has logging enabled. This is redirected to the stderr. Now, thread X's duty is to monitor stderr and read from it and process that for the main thread. This is, in summary, what's happening.

Upvotes: 2

Views: 6476

Answers (2)

user1277476
user1277476

Reputation: 2909

If you're on *ix and you have an interactive process, you can open('/dev/tty', 'r'). This is similar to reading from stderr. Note that open('/dev/tty", 'r+') only works in 2.x; in 3.x you need open('/dev/tty', 'r').

Upvotes: 1

Serge Ballesta
Serge Ballesta

Reputation: 148900

Well you cannot directly do what you want. If one thread writes to the default sys.stderr, by default it will go to the terminal, and it will be impossible to another thread to read that.

But ... you can always change sys.stderr to any object that has a write method taking a string argument (extract from the doc of the Standard Python Library sys module : stderr needn’t be built-in file objects: any object is acceptable as long as it has a write() method that takes a string argument. (Changing these objects doesn’t affect the standard I/O streams of processes executed by os.popen(), os.system() or the exec*() family of functions in the os module.))

In short : if you thread directly writes to sys.stderr, you could create a pair of pipes with os.pipe() affect the write end to sys.stderr, read the read end from the monitoring thread - than can still write to sys.__sterr__ or to a saved value of sys.stderr

If you thread launches subprocesses, do use a subprocess.Popen object to redirect the stderr stream of the subcommand to a pipe and read it from your monitoring thread.

Upvotes: 2

Related Questions