我在最后提出了一种方法来执行所要求的操作,但我不建议为此使用裸 prints。有更好的工具,如果你仍然想坚持使用print,你可以使用file关键字来指定输出应该去哪里。
import time
import sys
def get(out_stream=sys.stdout):
for i in range(100):
print(i, file=out_stream)
print("\n")
time.sleep(1)
您可以将使用open 打开的文件对象作为参数传递,输出将转到该文件。或者,您可以按照@barmar 的建议使用io.StringIO,并在get 完成后将内容写入文件。
所有其他选项都与sys.stdout 混淆,这是print 使用的默认文件对象(它是file 关键字参数的默认值)。这会影响使用sys.stdout 的所有内容,这可能比所有被执行的print 语句还要多。
如果您需要重定向裸print 语句(不使用print 的file 关键字),则必须替换sys.stdout。最明显的替代方法是使用输出文件对象:
from threading import Thread
import time
import sys
def get():
for i in range(100):
print(i)
time.sleep(1)
if __name__ == "__main__":
old_stdout = sys.stdout
with open("output.txt", "a") as text_fil:
sys.stdout = text_fil
get_thread = Thread(None, get)
get_thread.start()
get_thread.join()
sys.stdout = old_stdout
如果您需要一个写入线程和一个读取线程,正如问题所述,您可以使用队列,但更简单的方法是使用管道(我添加了一个调用 post 的虚拟线程 (postthread)使其类似于OP的使用):
from threading import Thread
import time
import sys
import os
def get():
for i in range(100):
print(i)
time.sleep(1)
def post(read_pipe):
with open("output.txt", "ab") as text_fil: # os.read yields bytes
try:
data = os.read(read_pipe, 65535) # arbitrary (but large) number
text_fil.write(data)
except Exception as e:
return True # the read descriptor was closed: quit
return len(data) == 0 # the write descriptor was closed: quit
def postthread(read_pipe):
for _ in range(21):
time.sleep(5)
if post(read_pipe):
return
if __name__ == "__main__":
old_stdout = sys.stdout
r_fd, w_fd = os.pipe()
with os.fdopen(w_fd, 'wt') as write_pipe: # write pipe is a file object
read_pipe = r_fd
sys.stdout = write_pipe
get_thread = Thread(None, get)
post_thread = Thread(None, postthread, args=(read_pipe, ))
post_thread.start()
get_thread.start()
get_thread.join()
sys.stdout = old_stdout
# closing the write pipe (and its file descriptor) causes read to see EOF.
post_thread.join()
os.close(r_fd)
sys.stdout = old_stdout