I'm currently using some functions to store all print
in Python
And it get all print
AFTER the function has finished
Here is a sample snippet
import io
import sys
import time
import traceback
def return_std(func):
def wrapper(*args, **kwargs):
old_stdout = sys.stdout
sys.stdout = buffer = io.StringIO()
try:
func(*args, **kwargs)
except:
print(traceback.format_exc())
finally:
sys.stdout = old_stdout
body = buffer.getvalue()
buffer.close()
return body
return wrapper
@return_std
def some_useful_function():
print('so this line is executed at ' + time.strftime('%X'))
time.sleep(5)
print('program execute at ' + time.strftime('%X'))
std_of_some_useful_function = some_useful_function()
print(std_of_some_useful_function)
print('but we can not know if it succeeded or failed before ' + time.strftime('%X'))
output
program execute at 11:11:11
so this line is executed at 11:11:11
but we can not know if it succeeded or failed before 11:11:16
This way captures all print
and error in some_useful_function
, and stores it as the function return. But print
will not show BEFORE this function has finished
How should I modify the wrapper return_std
, so I can see the output at 11:11:11
instantly (like it was really printed), and get all previous print
stored at 11:11:16
You can create a subclass of io.StringIO and override the write()
method so that it writes to a saved version of sys.stdout
aswell as writing to it's internal buffer
class SavedStdOut(io.StringIO):
def __init__(self, stdout):
super().__init__()
self.stdout = stdout
def write(self, s: str):
self.stdout.write(s)
return super().write(s)
The class then writes to the passed file and saves the written data
foo = SavedStdOut(sys.stdout)
foo.write('Hello\n') # Hello
print('Buffer:', foo.getvalue()) # Buffer: Hello
A complete example
import io
import sys
import time
import traceback
class SavedStdOut(io.StringIO):
def __init__(self, stdout):
super().__init__()
self.stdout = stdout
def write(self, s: str):
self.stdout.write(s)
return super().write(s)
def return_std(func):
def wrapper(*args, **kwargs):
sys.stdout = buffer = SavedStdOut(sys.stdout)
try:
func(*args, **kwargs)
except:
print(traceback.format_exc())
finally:
sys.stdout = buffer.stdout
body = buffer.getvalue()
buffer.close()
return body
return wrapper
@return_std
def some_useful_function():
print('so this line is executed at ' + time.strftime('%X'))
time.sleep(5)
print('program execute at ' + time.strftime('%X'))
std_of_some_useful_function = some_useful_function()
print('saved stdout:', std_of_some_useful_function)
print('but we can not know if it succeeded or failed before ' + time.strftime('%X'))
Output:
program execute at 03:52:01
so this line is executed at 03:52:01 # Printed as soon as print() is called
saved stdout: so this line is executed at 03:52:01
but we can not know if it succeeded or failed before 03:52:06