0

I have a function that does a lot of prints. I want these to go to stdout as well as to a file, so I currently have to duplicate every print: once for stdout and once for the file.

Is there a way I can print to something (not sure what!) that I can return from the function and simply print with two print statements in my calling script?

So instead of:

def func():
   print("1")
   print("1",file=out.txt)
   print("2")
   print("2",file=out.txt)
   print("3")
   print("3",file=out.txt)
   return()

I want something like:

def func2():
   print("1",  ???) ->string.out
   print("2",  ???) ->string.out
   print("3",  ???) ->string.out
   (or some such?)
   return(string.out)

func2()
print(string.out)
print(string.out,file=out.txt)

I know I can do it in a crude fashion by appending all my output to a string but this would involve lots of formatting that "print" takes care of (eg. with template).

Or maybe that's the answer - I just can't see how to do it in a neat pythonic fashion.

Seanny123
  • 8,776
  • 13
  • 68
  • 124
RustyC
  • 59
  • 3
  • Why don't you just use `tee` command ? – ymonad Oct 16 '19 at 02:30
  • 2
    I don't think I understood the problem. Why can't you define your own `my_print` function that prints the same thing to both stdout and the file? – Selcuk Oct 16 '19 at 02:31
  • So basically what you want is the output to be in console and the file at the same time ? – shuberman Oct 16 '19 at 02:32
  • You can "overload" builtins.print. Take a look here: https://stackoverflow.com/questions/46658639/decorating-pythons-builtin-print-function – outflanker Oct 16 '19 at 02:34
  • The `multiprint` function would work but I was looking for something that did the printing in the main routine (for various reasons). – RustyC Oct 16 '19 at 04:47

1 Answers1

0

The easiest way would be to define your own print function and call it instead of calling print.

def multiprint(data, *files):
    print(data)  # prints out to stdout
    for file in files:
        print(data, stdout=file)

And you can call this function as:

multiprint("print this", file1, file1, file3)

All you have to do is, replace all print function calls with multiprint calls.


Or, you can write a decorator, but it would be a horrible approach.

from functools import wraps
import sys

def multiprint(*files):
    def printnew(func):
        @wraps(func)
        def inner():
            func()
            _stdout = sys.stdout
            for file in files:
                sys.stdout = file  # a bit of dirty monkey patching
                func()
            sys.stdout = _stdout
        return inner
    return printnew


@multiprint(file1, file2)
def f():
    print('first')
    print('second')

f()  # first and second will be printed to stdout and into both file1 and file2
Diptangsu Goswami
  • 5,554
  • 3
  • 25
  • 36