在Python中,我怎么知道进程何时完成?

编程入门 行业动态 更新时间:2024-10-27 20:28:22
本文介绍了在Python中,我怎么知道进程何时完成?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

从Python GUI(PyGTK)中,我开始一个过程(使用多重处理).该过程需要很长时间(〜20分钟)才能完成.该过程完成后,我想清理一下(提取结果并加入过程).我怎么知道该过程何时完成?

From within a Python GUI (PyGTK) I start a process (using multiprocessing). The process takes a long time (~20 minutes) to finish. When the process is finished I would like to clean it up (extract the results and join the process). How do I know when the process has finished?

我的同事建议在父进程中进行繁忙的循环,以检查子进程是否已完成.当然有更好的方法.

My colleague suggested a busy loop within the parent process that checks if the child process has finished. Surely there is a better way.

在Unix中,当分叉进程时,子进程完成后,将从父进程中调用信号处理程序.但是我在Python中看不到类似的东西.我想念什么吗?

In Unix, when a process is forked, a signal handler is called from within the parent process when the child process has finished. But I cannot see anything like that in Python. Am I missing something?

如何从父流程中观察子流程的结束? (当然,我不想调用Process.join(),因为它会冻结GUI界面.)

How is it that the end of a child process can be observed from within the parent process? (Of course, I do not want to call Process.join() as it would freeze up the GUI interface.)

这个问题不仅限于多处理:对于多线程,我也有完全相同的问题.

This question is not limited to multi-processing: I have exactly the same problem with multi-threading.

推荐答案

这个答案真的很简单! (花了我几天来解决.)

This answer is really simple! (It just took me days to work it out.)

结合PyGTK的idle_add(),可以创建一个AutoJoiningThread.总代码是微不足道的:

Combined with PyGTK's idle_add(), you can create an AutoJoiningThread. The total code is borderline trivial:

class AutoJoiningThread(threading.Thread): def run(self): threading.Thread.run(self) gobject.idle_add(self.join)

如果您想做的不只是加入(例如收集结果),还可以扩展上面的类以在完成时发出信号,如以下示例所示:

If you want to do more than just join (such as collecting results) then you can extend the above class to emit signals on completion, as is done in the following example:

import threading import time import sys import gobject gobject.threads_init() class Child: def __init__(self): self.result = None def play(self, count): print "Child starting to play." for i in range(count): print "Child playing." time.sleep(1) print "Child finished playing." self.result = 42 def get_result(self, obj): print "The result was "+str(self.result) class AutoJoiningThread(threading.Thread, gobject.GObject): __gsignals__ = { 'finished': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()) } def __init__(self, *args, **kwargs): threading.Thread.__init__(self, *args, **kwargs) gobject.GObject.__init__(self) def run(self): threading.Thread.run(self) gobject.idle_add(self.join) gobject.idle_add(self.emit, 'finished') def join(self): threading.Thread.join(self) print "Called Thread.join()" if __name__ == '__main__': print "Creating child" child = Child() print "Creating thread" thread = AutoJoiningThread(target=child.play, args=(3,)) thread.connect('finished', child.get_result) print "Starting thread" thread.start() print "Running mainloop (Ctrl+C to exit)" mainloop = gobject.MainLoop() try: mainloop.run() except KeyboardInterrupt: print "Received KeyboardInterrupt. Quiting." sys.exit() print "God knows how we got here. Quiting." sys.exit()

以上示例的输出将取决于线程执行的顺序,但是它将类似于:

The output of the above example will depend on the order the threads are executed, but it will be similar to:

Creating child Creating thread Starting thread Child starting to play. Child playing. Running mainloop (Ctrl+C to exit) Child playing. Child playing. Child finished playing. Called Thread.join() The result was 42 ^CReceived KeyboardInterrupt. Quiting.

不可能以相同的方式创建AutoJoiningProcess(因为我们不能在两个不同的进程之间调用idle_add()),但是我们可以使用AutoJoiningThread来获得我们想要的东西:

It's not possible to create an AutoJoiningProcess in the same way (because we cannot call idle_add() across two different processes), however we can use an AutoJoiningThread to get what we want:

class AutoJoiningProcess(multiprocessing.Process): def start(self): thread = AutoJoiningThread(target=self.start_process) thread.start() # automatically joins def start_process(self): multiprocessing.Process.start(self) self.join()

为演示AutoJoiningProcess,这是另一个示例:

To demonstrate AutoJoiningProcess here is another example:

import threading import multiprocessing import time import sys import gobject gobject.threads_init() class Child: def __init__(self): self.result = multiprocessing.Manager().list() def play(self, count): print "Child starting to play." for i in range(count): print "Child playing." time.sleep(1) print "Child finished playing." self.result.append(42) def get_result(self, obj): print "The result was "+str(self.result) class AutoJoiningThread(threading.Thread, gobject.GObject): __gsignals__ = { 'finished': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()) } def __init__(self, *args, **kwargs): threading.Thread.__init__(self, *args, **kwargs) gobject.GObject.__init__(self) def run(self): threading.Thread.run(self) gobject.idle_add(self.join) gobject.idle_add(self.emit, 'finished') def join(self): threading.Thread.join(self) print "Called Thread.join()" class AutoJoiningProcess(multiprocessing.Process, gobject.GObject): __gsignals__ = { 'finished': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()) } def __init__(self, *args, **kwargs): multiprocessing.Process.__init__(self, *args, **kwargs) gobject.GObject.__init__(self) def start(self): thread = AutoJoiningThread(target=self.start_process) thread.start() def start_process(self): multiprocessing.Process.start(self) self.join() gobject.idle_add(self.emit, 'finished') def join(self): multiprocessing.Process.join(self) print "Called Process.join()" if __name__ == '__main__': print "Creating child" child = Child() print "Creating thread" process = AutoJoiningProcess(target=child.play, args=(3,)) process.connect('finished',child.get_result) print "Starting thread" process.start() print "Running mainloop (Ctrl+C to exit)" mainloop = gobject.MainLoop() try: mainloop.run() except KeyboardInterrupt: print "Received KeyboardInterrupt. Quiting." sys.exit() print "God knows how we got here. Quiting." sys.exit()

结果输出将与上面的示例非常相似,除了这次我们同时具有流程联接和伴随的线程联接:

The resulting output will be very similar to the example above, except this time we have both the process joining and it's attendant thread joining too:

Creating child Creating thread Starting thread Running mainloop (Ctrl+C to exit) Child starting to play. Child playing. Child playing. Child playing. Child finished playing. Called Process.join() The result was [42] Called Thread.join() ^CReceived KeyboardInterrupt. Quiting.

不幸的是:

  • 由于使用了idle_add(),因此此解决方案取决于gobject. PyGTK使用了gobject.
  • 这不是真正的父母/子女关系.如果这些线程中的一个由另一个线程启动,则仍将由运行mainloop的线程(而不是父线程)加入.这个问题也适用于AutoJoiningProcess,除了我认为会抛出异常之外.
  • 因此,使用这种方法,最好只在mainloop/GUI中创建线程/进程.

    Thus to use this approach, it would be best to only create threads/process from within the mainloop/GUI.

    更多推荐

    在Python中,我怎么知道进程何时完成?

    本文发布于:2023-08-02 13:25:53,感谢您对本站的认可!
    本文链接:https://www.elefans.com/category/jswz/34/1278168.html
    版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
    本文标签:进程   我怎么   Python

    发布评论

    评论列表 (有 0 条评论)
    草根站长

    >www.elefans.com

    编程频道|电子爱好者 - 技术资讯及电子产品介绍!