Search code examples
pythonfileconsole-output

Pipe console outputs from a specific function into a file - python


I have a function that I cannot edit and it prints results onto the console. Is it possible to calls that function but pipes the console output into a file without changing the internal code of the function?

For example, I have:

def somefunc(x):
  print "Hello World", x**x

def pipeout(func, outfilename)
  with open('outfilename', 'w') as fout:
    # somehow pipes out the output...

I couldn't use logger because I couldn't edit the somefunc().

I have tried @Aशwini चhaudhary 's solution but i couldn't the files were empty other than the first outputfile and also it overwrites that file again and again.:

def redirect_output(file_name):
  def decorator(func):
    def wrapper(*args):
      with open(file_name, 'w') as f:
        original_stdout = sys.stdout
        sys.stdout = f
        func(*args)
      sys.stdout = original_stdout
    return wrapper
  return decorator

def somefunc(x):
  print x*x

xs = [1,2,3,4]

for i in xs:
  outputfilename = 'results/'+str(i)
  somefunc = redirect_output(outputfilename)(somefunc)
  somefunc(i)

Solution

  • You can use a decorator to redirect the sys.stdout to a file object when the function gets called and later restores it back to original STDOUT.

    import sys
    
    def redirect_output(file_name):
    
        def decorator(func):
            def wrapper(*args):
                with open(file_name, 'w') as f:
                    original_stdout = sys.stdout
                    sys.stdout = f
                    func(*args)
                sys.stdout = original_stdout
            return wrapper
        return decorator
    
    @redirect_output('file.txt')
    def somefunc(x):
      print "Hello World", x**x
    
    
    somefunc(2)
    
    print 'Hello to console.'
    

    Output:

    >>> %run so.py
    Hello to console.
    >>> !cat file.txt
    Hello World 4
    

    Update:

    Working version of your latest code:

    for i in xs:
      outputfilename = 'results/'+str(i)
      new_func = redirect_output(outputfilename)(somefunc)
      #or call it directly
      #redirect_output(outputfilename)(somefunc)(i)
      new_func(i)