Python、多处理和GUI
我有一个带有GUI的程序,需要进行一些多处理。其要点是避免冻结GUI,并允许用户在进程运行时使用其他一些按钮 然后我想定义一个如下所示的方法:Python、多处理和GUI,python,python-2.7,multiprocessing,gtk3,pygobject,Python,Python 2.7,Multiprocessing,Gtk3,Pygobject,我有一个带有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 e
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()
之后执行的代码指示进程的结束时间。我将使用该代码更新等待窗口的取消按钮
然后,我想到了另一种解决方案来避免使用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 a AuthenticationString对象是'
TypeError:出于安全原因,不允许酸洗AuthenticationString对象
这让我想到了,但我还没有解决这个问题:/您的第一个示例应该如下所示:
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()
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.
按照您的方式,它实际上不是在子进程中执行func
;它在父进程中执行它,然后将返回值传递给进程
。调用task.start()
时,它可能会立即失败,因为您传递的是func
返回的内容,而不是函数对象
请注意,因为您正在调用task.join()
内部start\u waiting
,它可能会阻塞您的GUI,因为start\u waiting
在func
完成之前不会返回,即使它在子进程中运行。它不会阻塞的唯一方法是在GUI事件循环的单独线程中运行start\u waiting
。你可能想要更像这样的东西:
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()
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.
问题是join()函数不起作用
如何?@collone函数join()之后的代码在任务
完成之前执行(我很难理解这一点,因为这是join()函数的滚动)。具体一点是没有坏处的。它也可能抛出错误或其他东西。@Yep上校,你说得对:)我刚刚尝试更改task=Process(target=func,args=args)
,但我得到了相同的结果:/,谢谢你的提示,这解释了我以前遇到的问题。我仍然不知道如何实现这个GUI/多处理。你能看看我的节目吗?我刚开始编程,这真的很难解决>“在一个单独的线程中”我倾向于混淆线程和进程,我会好好看看。除了使用线程,我什么都试过了@rsm在func
中发生了什么?你确定它不会因为某些原因而比你预期的更早失败或结束吗?我已经使用了多处理。Process
很多次,而join
的工作原理与它的预期完全一样。第一次它不工作(我不知道为什么,它应该像你说的那样工作,阻塞GUI)。相反,我按照您的建议创建了两个函数,并创建了第三个函数change\u button
,其代码为`。。。只有在任务结束时才应该执行的代码…`我在join()之后添加了GLib.idle\u add(change\u按钮)
,它工作得非常好@rsm您肯定不想尝试从子进程更新GUI!只要您使用GLib.idle\u add