你如何在Popen注册回调?

时间:2017-01-17 20:16:12

标签: python python-3.x process callback

一位朋友想要编写一些代码,以便在Popen完成运行后,执行回调。这是一个需要的示例程序,应该有助于制定正确的答案:

#! /usr/bin/env python3
from subprocess import Popen


def main():
    handle = Popen(('cmd', '/c', 'pause'))
    handle.register_callback(Popen, ('cmd', '/c', 'echo', 'THE END'))


if __name__ == '__main__':
    main()

在API中提供register_callback方法的最简单方法是什么?

2 个答案:

答案 0 :(得分:1)

为了避免阻塞主线程的处理以便它可以执行其他操作,您可以创建一个单独的线程轮询该过程以查看是否已完成:

from subprocess import Popen
from threading import Thread
import time

class Process(Popen):
    def register_callback(self, callback, *args, **kwargs):
        Thread(target=self._poll_completion, args=(callback, args, kwargs)).start()

    def _poll_completion(self, callback, args, kwargs):
        while self.poll() is None:
            time.sleep(0.1)
        callback(*args, **kwargs)

def main():
    handle = Process(('cmd', '/c', 'echo', 'process finished'))
    handle.register_callback(my_callback)

def my_callback():
    print("It's done!")

if __name__ == '__main__':
    main()

答案 1 :(得分:0)

此问题的一个解决方案是引入另一个继承自Popen并提供register_callback方法的类。以下程序演示了如何轻松实现这一目标:

#! /usr/bin/env python3
from subprocess import Popen
from threading import Thread


def main():
    handle = Process(('cmd', '/c', 'pause'))
    handle.register_callback(Process, ('cmd', '/c', 'echo', 'THE END'))


class Process(Popen):

    def register_callback(self, callback, *args, **kwargs):
        Thread(target=self.__bootstrap, args=(callback, args, kwargs)).start()

    def __bootstrap(self, callback, args, kwargs):
        self.wait()
        callback(*args, **kwargs)


if __name__ == '__main__':
    main()

这个答案可能并不适用于所有应用程序,但在特定情况下有效。