brianmearns
brianmearns

Reputation: 9967

Wrapper to write to multiple streams

In python, is there an easy way to set up a file-like object for writing that is actually backed by multiple output streams? For instance, I want something like this:

file1 = open("file1.txt", "w")
file2 = open("file2.txt", "w")
ostream = OStreamWrapper(file1, file2, sys.stdout)

#Write to both files and stdout at once:
ostream.write("ECHO!")

So what I'm looking for is OStreamWrapper. I know it'd be pretty easy to write my own, but if there's an existing one, I'd rather use that and not have to worry about finding and covering edge cases.

Upvotes: 5

Views: 2014

Answers (3)

Niklas R
Niklas R

Reputation: 16870

class OStreamWrapper(object):

    def __init__(self, *streams):
        self.streams = list(streams)

    def write(self, string):
        for stream in self.streams:
            stream.write(string)

    def writelines(self, lines):
        # If you want to use stream.writelines(), you have
        # to convert lines into a list/tuple as it could be
        # a generator.
        for line in lines:
            for stream in self.streams:
                stream.write(line)

    def flush(self):
        for stream in self.streams:
            stream.flush()

Upvotes: 4

reclosedev
reclosedev

Reputation: 9502

Way to wrap all public file functions:

import sys

def _call_for_all_streams(func_name):
    def wrapper(self, *args, **kwargs):
        result = []
        for stream in self._streams:
            func = getattr(stream, func_name)
            result.append(func(*args, **kwargs))
        return result
    return wrapper

class OStreamWrapper(object):
    def __init__(self, *streams):
        self._streams = streams

for method in filter(lambda x: not x.startswith('_'), dir(file)):
    setattr(OStreamWrapper, method, _call_for_all_streams(method))

if __name__ == '__main__':
    file1 = open("file1.txt", "w")
    file2 = open("file2.txt", "w")
    ostream = OStreamWrapper(file1, file2, sys.stdout)
    ostream.write("ECHO!")
    ostream.close()

But it's kinda dirty.

Upvotes: 3

Drake Guan
Drake Guan

Reputation: 15122

Logbook is another option although it is more than that. Its handlers are more powerful and you can combine whatever you like.

Upvotes: 0

Related Questions