【问题标题】:Stopping a process pygtk停止进程 pygtk
【发布时间】:2014-07-17 14:25:17
【问题描述】:

我正在尝试制作一个简单的应用程序来使用 pygtk 播放和停止 MIDI 文件。

这是我目前所拥有的:

import pygtk
pygtk.require('2.0')
import gtk
import subprocess


class Teacher:

    def __init__(self):

        window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        window.set_size_request(400, 200)
        window.set_title("Music Teacher")
        window.connect("delete_event",
                   lambda w,e: gtk.main_quit())

        table = gtk.Table(4, 4, True)
        window.add(table)

        play = gtk.Button("Play")
        play.connect("clicked", self.clicked_play)
        play.show()

        stop = gtk.Button("Stop")
        stop.show()

        table.attach(play, 0, 1, 0, 1)
        table.attach(stop, 0, 1, 1, 2)

        window.show_all()

    def clicked_play(self, widget):
        subprocess.Popen(["timidity", "~/somefile.mid"])

    def main(self):
        gtk.main()
        return 0


Teacher().main()

我可以从 stop 和 delete_event 发送中断来终止进程吗?我应该使用线程吗?

【问题讨论】:

标签: python subprocess pygtk


【解决方案1】:

您可以像这样处理获取SIGTERM、Ctrl+C 或停止按钮:

import pygtk
pygtk.require('2.0')
import gtk
import subprocess
import signal


class Teacher:

    def __init__(self):
        self.proc = None  # Initialize the handle to our subprocess
        window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        window.set_size_request(400, 200)
        window.set_title("Music Teacher")
        window.connect("delete_event",
                   lambda w,e: gtk.main_quit())

        table = gtk.Table(4, 4, True)
        window.add(table)

        play = gtk.Button("Play")
        play.connect("clicked", self.clicked_play)
        play.show()

        stop = gtk.Button("Stop")
        stop.connect("clicked", self.clicked_stop)
        stop.show()

        table.attach(play, 0, 1, 0, 1)
        table.attach(stop, 0, 1, 1, 2)

        window.show_all()

    def clicked_play(self, widget):
        self.proc = subprocess.Popen(["timidity", "~/somefile.mid"])

    def clicked_stop(self, widget=None):
        if self.proc:
            self.proc.terminate()
            self.proc.wait()

    def handle_sigterm(self, *args):
        self.clicked_stop()
        sys.exit()

    def main(self):
        signal.signal(signal.SIGTERM, self.handle_sigterm)
        try:
            gtk.main()
        except KeyboardInterrupt:
            self.clicked_stop()
            raise
        return 0


Teacher().main()

我们只需保存对在clicked_play 中创建的Popen 对象的引用,然后使用该句柄通过click_stop 中的terminate 实例方法将SIGTERM 发送到进程。然后我们调用wait(它应该立即结束,除非timidity 没有在SIGTERM 上关闭)来获取终止的进程(所以它不会留下僵尸)。

我还在对gtk.main() 的调用周围添加了try/except,以便在您发出Ctrl+C 和SIGTERM 处理程序时会调用clicked_stop,如果那样的话接收信号。

【讨论】:

  • 非常感谢!我不明白为什么我们在调用 clicked_stop 时使用 signal.signal(signal.SIGTERM, self.clicked_stop) 不会 'terminate()' 杀死进程?
  • @AdaXu 该行实际上为 GUI 进程注册了一个信号处理程序,而不是我们正在启动的子进程。它的用途是,如果有人向您的 GUI 进程发送 SIGTERM,我们可以确保在 GUI 脚本退出之前终止 timidity
  • @AdaXu 实际上我刚刚注意到SIGTERM 处理中的一个错误。现在应该修好了。
猜你喜欢
  • 1970-01-01
  • 2012-10-17
  • 1970-01-01
  • 2018-11-04
  • 1970-01-01
  • 1970-01-01
  • 2018-01-15
  • 2012-08-22
相关资源
最近更新 更多