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

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

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

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

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

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

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

import threadingimport timeimport sysimport gobjectgobject.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()

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

创造孩子创建线程启动线程孩子开始玩。 小孩玩。运行主循环(Ctrl + C退出)小孩玩。小孩玩。孩子玩完了。叫做Thread.join()结果是42^ C收到KeyboardInterrupt。退出

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

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,这里是另一个示例:

import threadingimport multiprocessingimport timeimport sysimport gobjectgobject.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()

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

创造孩子创建线程启动线程运行主循环(Ctrl + C退出) 孩子开始玩。小孩玩。小孩玩。小孩玩。孩子玩完了。称为Process.join()结果是[42]叫做Thread.join()^ C收到KeyboardInterrupt。退出

不幸:

  1. 由于使用了idle_add(),因此此解决方案取决于gobject。gobject由PyGTK使用。
  2. 这不是真正的父母/子女关系。如果这些线程之一是由另一个线程启动的,那么它将由运行mainloop的线程(而不是父线程)加入。这个问题也适用于AutoJoiningProcess,除非我想象会抛出异常。

因此,要使用这种方法,最好只在mainloop / GUI中创建线程/进程。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5647593.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存