当前位置: 首页 > 面试题库 >

如何将python multiprocessing Process输出发送到Tkinter GUI

党佐
2023-03-14
问题内容

我正在尝试从Tkinter gui中显示的python multiprocessing进程获取输出。

我可以通过gui将进程的输出发送到命令外壳,例如,通过在外壳提示符下运行下面的微小脚本:

from multiprocessing import Process  
import sys

def myfunc(text):    
    print text  
    sys.stdout.flush()

def f1():  
    p1 = Process(target = myfunc, args = ("Surprise",))  
    p1.start()

def f2():  
    p2 = Process(target = myfunc, args = ("Fear",))  
    p2.start()

def fp():  
    myfunc("... and an almost fanatical devotion to the Pope")

a = Tk()

b1 = Button(a, text="Process 1", command=f1)  
b1.grid(row=0, column=0, pady=10, padx=10, sticky=SE)  
b2 = Button(a, text="Process 2", command=f2)  
b2.grid(row=0, column=1, pady=10, padx=10, sticky=SE)  
b3 = Button(a, text="Parent", command=fp)  
b3.grid(row=0, column=2, pady=10, padx=10, sticky=SE)

if __name__ == "__main__":  
    a.mainloop()

我还可以将输出从 父级 发送到文本框,例如,通过注释掉myfunc中的stdout的刷新来修改上面的内容

#    sys.stdout.flush()

并在“ b3.grid …”行之后立即添加以下内容:

class STDText(Text):
    def __init__(self, parent, cnf={}, **kw):
        Text.__init__(self, parent, cnf, **kw)
    def write(self, stuff):
        self.config(state=NORMAL)
        self.insert(END, stuff)
        self.yview_pickplace("end")
        self.config(state=DISABLED)

messages = STDText(a, height=2.5, width=30, bg="light cyan", state=DISABLED)   
messages.grid(row=1, column=0, columnspan=3)
sys.stdout = messages

但是我不知道如何将输出从进程发送到文本框。我是否缺少简单的东西?


问题答案:

您可以将stdout /
stderr重定向到myfunc()中的StringIO,然后将写入该StringIO的所有内容发送回父级(如unutbu所建议)。

由于该示例的功能超出了您的需要,因此以下版本更符合您的既定目标:

#!/usr/bin/env python
import sys
from cStringIO import StringIO
from code import InteractiveConsole
from contextlib import contextmanager
from multiprocessing import Process, Pipe

@contextmanager
def std_redirector(stdin=sys.stdin, stdout=sys.stdin, stderr=sys.stderr):
    tmp_fds = stdin, stdout, stderr
    orig_fds = sys.stdin, sys.stdout, sys.stderr
    sys.stdin, sys.stdout, sys.stderr = tmp_fds
    yield
    sys.stdin, sys.stdout, sys.stderr = orig_fds

class Interpreter(InteractiveConsole):
    def __init__(self, locals=None):
        InteractiveConsole.__init__(self, locals=locals)
        self.output = StringIO()
        self.output = StringIO()

    def push(self, command):
        self.output.reset()
        self.output.truncate()
        with std_redirector(stdout=self.output, stderr=self.output):
            try:
                more = InteractiveConsole.push(self, command)
                result = self.output.getvalue()
            except (SyntaxError, OverflowError):
                pass
            return more, result

def myfunc(conn, commands):
    output = StringIO()
    py = Interpreter()
    results = ""

    for line in commands.split('\n'):
        if line and len(line) > 0:
            more, result = py.push(line + '\n')
            if result and len(result) > 0:
                results += result

    conn.send(results)
    conn.close()

if __name__ == '__main__':
    parent_conn, child_conn = Pipe()

    commands = """
print "[42, None, 'hello']"

def greet(name, count):
    for i in range(count):
        print "Hello, " + name + "!"

greet("Beth Cooper", 5)
fugazi
print "Still going..."
"""
    p = Process(target=myfunc, args=(child_conn, commands))
    p.start()
    print parent_conn.recv()
    p.join()

有关安全性的通常警告适用于此(即,除非您可以相信这些代码段的发送者不要做任何愚蠢/恶意的操作,否则请不要这样做。)

另请注意,如果您不需要解释python表达式 语句的任意组合,则可以简化很多操作。如果只需要调用生成某些输出的顶级函数,则可能更合适:

def dosomething():
    print "Doing something..."

def myfunc(conn, command):
    output = StringIO()
    result = ""
    with std_redirector(stdout=output, stderr=output):
        try:
            eval(command)
            result = output.getvalue()
        except Exception, err:
            result = repr(err)

    conn.send(result)
    conn.close()

if __name__ == '__main__':
    parent_conn, child_conn = Pipe()
    command = "dosomething()"
    p = Process(target=myfunc, args=(child_conn, command))
    p.start()
    print parent_conn.recv()
    p.join()


 类似资料:
  • 问题内容: 我可以导入什么以模拟Java中的键盘按下? 因此,例如,我可以使用它制作一个程序,以便在事件发生时自动按下“ a”键。 问题答案: 您需要的一切都在 例:

  • 问题内容: 我有两个卡夫卡喷口,我要将其值发送到同一螺栓。 可能吗 ? 问题答案: 是的,有可能: 您也可以使用任何其他分组。 更新: 为了区分使用者螺栓中的元组(即topic_1或topic_2),有两种可能性: 1)您可以使用操作员ID(如@ user-4870385所建议): 2)您可以使用流名称(@zenbeni建议)。对于这种情况,两个喷口都需要声明命名流,而螺栓需要通过流名称连接到喷口

  • 问题内容: 我有一个现有的应用程序,它针对log4j进行所有日志记录。我们使用了许多其他库,它们也使用log4j或对照Commons Logging进行日志记录,而这些日志最终在我们的环境中使用log4j记录。我们的依赖项之一甚至针对slf4j记录日志,它也可以正常工作,因为它最终也可以委托给log4j。 现在,我想为一些缓存需求将ehcache添加到此应用程序。先前版本的ehcache使用com

  • 我最终尝试使用维特尔蒂API发送传真。我在 EC2 上有一个 API,我从我的 React 原生应用程序调用它: 但是,这会返回错误。如果我将的值改为类似于

  • 问题内容: 我有。我希望在运行时在终端中显示ddrescue并将输出写入文件drclog。我尝试使用,但这使我在ddrescue中输入错误。 问题答案: 如果将其stdout / stderr重定向到管道时仍不更改其输出,则可以使用实用程序在终端上显示输出并将其保存到文件中: 如果确实如此,那么您可以尝试使用实用程序提供一个伪tty : 如果它直接写入终端,则可以用来捕获输出: 默认情况下,输出保

  • 问题内容: 我的工作按日期处理数据,需要将输出写入特定的文件夹结构。当前的期望是生成如下结构: 等等 在任何时候,我最多只能获得12个月的数据,因此,我正在使用类在驱动程序中使用以下函数创建12个输出: 在reducer中,我添加了一个清理功能,以将生成的输出移动到适当的目录。 问题:在将输出从_temporary目录移动到输出目录之前,reducer的清除功能正在执行。因此,由于所有数据仍位于_