Reputation: 9967
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
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
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
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