【问题标题】:Python, Multiprocessing and GUIPython、多处理和 GUI
【发布时间】:2014-08-08 13:24:31
【问题描述】:

我有一个带有 GUI 的程序需要进行一些多处理。这样做的目的是避免冻结 GUI,并允许用户在进程运行时使用其他一些按钮。

然后我想定义如下方法:

def start_waiting(self, parent, func, args):

    self.window_waiting.show()

    task=Process(func(*args))
    task.start()

    task.join()

    # Some code to execute at the end of the process
    #
    #...

问题是join() 不起作用,我需要它,因为join() 之后执行的代码表明Process 何时结束。我将使用该代码更新window_waiting 的取消按钮。

然后我想到了另一个避免使用join() 的解决方案,我将其替换为:

while task.is_alive():
    time.sleep(0.5)

但这两个都不起作用,所以我尝试了一个方案 C,即创建一个队列:

def worker(input, output):
    for func, args in iter(input.get, 'STOP'):
        result=func(*args)
        output.put(result)


task_queue = Queue()
done_queue = Queue()
task_queue.put(task)

Process(target=worker, args=(task_queue, done_queue)).start()
done_queue.get()

最后一个代码给了我错误:'Pickling an AuthenticationString object is ' TypeError: Pickling an AuthenticationString object is disallowed for security reasons

这导致我到multiprocessing.Process subclass using shared queue,但我还没有设法解决问题:/

【问题讨论】:

  • The problem is that the join() function is not working 怎么样?
  • @Colonel 函数join()之后的代码在taskfinish之前执行
  • (我很难理解这是因为那是 join() 函数的作用)
  • 具体一点永远不会有坏处。它也可能引发错误或其他问题。
  • @Colonel 是的,你是对的 :)

标签: python python-2.7 multiprocessing gtk3 pygobject


【解决方案1】:

您的第一个示例应如下所示:

def start_waiting(self,parent,func,args):

    ...not relevant code..

    self.window_waiting.show()


    task=Process(target=func, args=args)  # This line is different.
    task.start()


    task.join()

按照你的方式,它实际上并没有在子进程中执行func;它在父进程中执行,然后将返回值传递给Process。当您调用 task.start() 时,它可能会立即失败,因为您传递的是 func 返回的任何内容,而不是函数对象。

请注意,因为您在start_waiting 中调用task.join(),它可能会阻塞您的GUI,因为start_waiting 将在func 完成之前返回,即使它在子进程中运行。它不会阻塞的唯一方法是,如果您在与 GUI 事件循环不同的线程中运行 start_waiting。你可能想要更多这样的东西:

def start_waiting(self,parent,func,args):

    ...not relevant code..

    self.window_waiting.show() # You should interact with the GUI in the main thread only.

    self.task = Process(target=func, args=args)  # This line is different.
    self.thrd = threading.Thread(target=self.start_and_wait_for_task)
    self.thrd.start()


def start_and_wait_for_task(self):
    """ This runs in its own thread, so it won't block the GUI. """
    self.task.start()
    self.task.join()
    # If you need to update the GUI at all here, use GLib.idle_add (see https://wiki.gnome.org/Projects/PyGObject/Threading)
    # This is required to safely update the GUI from outside the main thread.

【讨论】:

  • 我刚刚尝试更改task=Process(target=func, args=args),但我得到了相同的结果:/,感谢您的说明,这解释了我以前遇到的问题。我仍然不知道我应该如何实现这个 GUI/多处理。你可以看看我的程序吗?我刚开始编程,这真的很难解决>.
  • “在一个单独的线程中”我倾向于混淆线程和进程,我会好好研究一下。除了使用线程,我什么都试过了!
  • @rsm func 发生了什么?您确定它不会因某种原因而比您预期的更早失败或结束吗?我已经多次使用multiprocessing.Process,而join 的工作方式一直与预期完全一样。
  • 第一次不工作(我不知道为什么,它应该像你说的那样工作,阻止GUI)。相反,我按照您的建议创建了两个函数,并创建了第三个函数change_button,其代码为` ...仅在任务结束时才应执行的代码...`,我在加入后添加了GLib.idle_add(change_button)( ) 并且效果很好!!
  • @rsm 您绝对不想尝试从子进程更新 GUI!只要您使用GLib.idle_add,从单独的线程执行它是可以的
猜你喜欢
  • 1970-01-01
  • 2013-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
  • 2012-06-11
相关资源
最近更新 更多