【问题标题】:Is it possible to get another thread's print content?是否可以获取另一个线程的打印内容?
【发布时间】:2022-01-13 09:23:31
【问题描述】:

我会在不同的线程中同时执行两个方法getpost,第一个方法get会持续很长时间(100秒),第二个请求post会重复5秒。这里get请求会打印很多如下

import time
def get():
    for i in range(100):
        print(i)
        print("\n")
        time.sleep(1)

post需要做的是收集get的所有打印内容,并在每次执行时追加到一个txt中(如果文件存在,则将新内容添加到txt中)。这是伪代码。

def post(request):
    print_from_get = sys.stdout
    with open("output.txt", "w") as text_file:
        text_file.write(print_from_get)

我的问题是我们是否可以从get 收集打印件,如果可以的话,我应该怎么做?

【问题讨论】:

  • 您应该将sys.stdout 设置为io.StringIO 流。
  • print 是一个错误的工具——stdout 纯粹是作为一个 输出 流。与其尝试破解 stdout 的某些不该做的事情,不如使用 queue.Queue 或类似名称。
  • @MisterMiyagi queue 当然是更好的解决方案,问题是我必须导入我同事的代码,他们的代码中也有打印。 post 必须收集所有打印内容包括外部包。
  • @Barmar 你能把它写成threading的答案吗
  • 我会先和同事谈谈,以确定他们是否应该使用print,或者他们是否应该切换到使用队列。

标签: python python-3.x multithreading


【解决方案1】:

我在最后提出了一种方法来执行所要求的操作,但我不建议为此使用裸 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 语句(不使用printfile 关键字),则必须替换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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-24
    • 2011-09-25
    • 2014-08-21
    • 1970-01-01
    相关资源
    最近更新 更多