I want to collect all of the print content and save them in a txt file. I use this answer's method to generate and collect logs. Also I use a threading
because I may have to collect the first 5 seconds' logs for instance.
import sys
import io
import time
import threading
import traceback
class MyThread(threading.Thread):
def __init__(self, func, args):
super(MyThread, self).__init__()
self.func = func
self.args = args
def run(self):
try:
self.result = self.func(*self.args)
except Exception as e:
f = traceback.format_exc()
print(f'{f}')
def get_result(self):
try:
return self.result
except Exception:
return None
def make_logs(delay):
for i in range(100):
print(i)
print("\n")
time.sleep(delay)
def get_logs(t1):
if t1.is_alive():
sys.stdout = old_stdout
whatWasPrinted = buffer.getvalue()
with open("output.txt", "w") as text_file:
text_file.write(whatWasPrinted)
time.sleep(1)
get_logs(t1)
def do_it():
t1 = MyThread(make_logs, args=(1,))
t2 = MyThread(get_logs, args=(t1,))
t1.start(), t2.start()
t1.join(), t2.join()
old_stdout = sys.stdout
sys.stdout = buffer = io.StringIO()
do_it()
However, as I execute this code, I can only write the first elment(0) to txt file. Anyone knows why? Thanks.
CodePudding user response:
You don't need two threads to capture the first N seconds – you can write a filelike object that stops writing to whatever backing object (here it just derives from io.StringIO
but could wrap another IO) when it has had enough.
import contextlib
import io
import threading
import time
def make_logs(n, delay):
for i in range(n):
print(i)
print("\n")
time.sleep(delay)
class StdoutCapturer(io.StringIO):
def __init__(self, time_limit):
super().__init__()
self.time_limit = time_limit
# This could be initialized later, at the first write:
self.start_time = time.time()
def write(self, s: str) -> int:
elapsed = time.time() - self.start_time
if elapsed < self.time_limit:
return super().write(s)
return 0
if __name__ == "__main__":
sio = StdoutCapturer(time_limit=3.1)
with contextlib.redirect_stdout(sio):
t = threading.Thread(target=make_logs, args=(5, 1))
t.start()
t.join()
print(repr(sio.getvalue()))
This prints out
'0\n\n\n1\n\n\n2\n\n\n3\n\n\n'
CodePudding user response:
you can use sys
:
import sys
sys.stdout = open(PATH_TO_LOG_FILE, "w")
do_it()
sys.stdout.close()
you can also use contextlib.redirect_stdout
: (works for python 3.4 )
from contextlib import redirect_stdout
with open('help.txt', 'w') as f:
with redirect_stdout(f):
print('it now prints to `help.text`')