How to overload the print function to expand its functionality?

I am wondering if it is possible to override the built-in print function so that the next statement writes to the console and the file at the same time.

 print("test0","test1","test2",sep='\n') 

Also, can I find out if the source code of the print built-in function can be changed?

+5
source share
4 answers

You can create a class using the write method and inside this method you can print and stdout , as well as write to a file.

 import sys class A(object): def __init__(self, f): self.f = open(f, 'w') def __enter__(self): return self # return instance of A which is assign to `f`. def write(self, text): sys.stdout.write(text) # print to the shell self.f.write(text) # write in the file def __exit__(self, *args): self.f.close() return True with A('foo.txt') as f: print("test0","test1","test4",sep='\n', file=f) #`file = f` calls `write` method 
+6
source

Use a decorator. A simplified example:

 def my_decorator(func): def wrapped_func(*args,**kwargs): return func("I've been decorated!",*args,**kwargs) return wrapped_func print = my_decorator(print) 

Test:

 print("TESTING") #I've been decorated! TESTING 

So, to print to a file at the same time, you can:

 def super_print(filename): '''filename is the file where output will be written''' def wrap(func): '''func is the function you are "overriding", ie wrapping''' def wrapped_func(*args,**kwargs): '''*args and **kwargs are the arguments supplied to the overridden function''' #use with statement to open, write to, and close the file safely with open(filename,'a') as outputfile: outputfile.write(*args,**kwargs) #now original function executed with its arguments as normal return func(*args,**kwargs) return wrapped_func return wrap print = super_print('output.txt')(print) 

If you compare this with the above example, you will see that there is additional closure in this situation (i.e. return wrapped_func AND return wrap instead of return wrapped_func ). This second close allows us to send an additional argument ( filename ) to the wrapper / decorator function.

The syntax for this last line looks a little strange, but this is the right way. Calling super_print('output.txt') returns an object, which then receives the print function object as an additional argument. All this works through closure; explore them if you are not in speed.

Then:

 print('test') 

test will be written to console output and output.txt.

+2
source

print function uses sys.stdout if no explicit file parameter is specified.

You can redirect sys.stdout to a file-like object that writes to the console and file at the same time:

 #!/usr/bin/env python3 import sys from contextlib import redirect_stdout class TeeFile: # write to multiple files at once def __init__(self, *files): self.files = files def write(self, data): for file in self.files: file.write(data) def flush(self): for file in self.files: file.flush() with open('log', 'a') as log, redirect_stdout(TeeFile(log, sys.stdout)): print("test0", "test1", "test2", sep='\n') 

redirect_stdout introduced in Python 3.4, but is easy to implement on earlier versions .

You can replace the builtins.print function if you want to replace the print function globally. See if the logging module is a better solution than the print function in your case.

0
source

Maybe a little late for this answer, but I created a package ( https://github.com/phohenecker/stream-to-logger ) that provides exactly what you are looking for, namely redirecting stdout + stderr to a file (in addition to normal screen printing).

It's super simple, you just need to add two lines to your code:

 import streamtologger streamtologger.redirect(target="./all-output.log") 

You can install the package using pip:

 pip install git+https://github.com/phohenecker/stream-to-logger 
0
source

Source: https://habr.com/ru/post/1209774/


All Articles