1

スレッドでbashスクリプトを実行し、いくつかのメッセージを表示するときにプログレスバーをパルス状にしたいPythonプログラムがあります。

ボタンをクリックすると、スレッドが開始されてスクリプトが起動されますが、メッセージとプログレスバーは、スレッドが終了したときにのみ応答し、最後のメッセージのみが表示されます。

読んで、メインループをブロックしていることは理解しましたが、これを解決する方法がわかりません。

私のプログラムの簡略化されたコード、問題は「on_fixme_button_pressed」を呼び出すときです:

from gi.repository import Gtk, Gdk, Pango, GObject, GLib
import os, sys
import xml.etree.ElementTree as etree
from urllib.request import urlopen
from subprocess import Popen
import threading


UI_FILE = "remendo_gtk.ui"
#UI_FILE = "/usr/local/share/remendo_gtk/ui/remendo_gtk.ui"

GObject.threads_init()

class GUI:

    def __init__(self):

        self.builder = Gtk.Builder()
        self.builder.add_from_file(UI_FILE)
        self.builder.connect_signals(self)

        self.window = self.builder.get_object('remendo')
        self.event_treeview = self.builder.get_object('event_treeview')
        self.event_info = self.builder.get_object('event_info')
        self.progressbar = self.builder.get_object('progressbar')
        self.progressbar_lock = threading.Lock()

        self.selected_event = ''
        self.url_script = ''
        self.local_script = ''
        self.window.connect("destroy", lambda _: Gtk.main_quit())
        self.set_event_list()

        self.window.show_all()

    def pulse_progressbar(self):
        if threading.active_count() > 1:
            self.progressbar.pulse()
            return True

        self.progressbar.set_fraction(0.0)
        self.progressbar_lock.release()
        return False

    def on_fixme_button_clicked(self, button):
        self.event_info.set_label("Fixing now...")
        script = threading.Thread(target=self.run_script(), args=(self,))
        script.start()

        if self.progressbar_lock.acquire(False):
            GLib.timeout_add(250, self.pulse_progressbar)

    def run_script(self):
        try:
            self.local_script = '/tmp/%s.sh' % self.selected_event.replace(" ", "_")
            script = urlopen(self.url_script)
            localscript = open(self.local_script, 'wb')
            localscript.write(script.read())
            localscript.close()

            command = ['bash', self.local_script]
            p = Popen(command)
            p.communicate()

            #self.event_solved()
            self.event_info.set_label("My work is done. Good day!")
        except:
            self.event_info.set_label("Script failed: %s" % self.local_script)

        return False


def main():
    app = GUI()
    Gtk.main()

if __name__ == "__main__":
    sys.exit(main())
4

4 に答える 4

1

を使用する場合subprocess.Popenは、返されたハンドラを で待ちます.wait()。プロセスが [および終了コード] を完了したかどうかを調査し.poll()たり、.communicate().

ドキュメントはここにあります: http://docs.python.org/2/library/subprocess.html#module-subprocess

何を試しましたか?

于 2013-06-15T19:21:48.140 に答える
0

役立つかどうかはわかりませんが、Pexpect モジュールをご覧になることをお勧めします: http://pexpect.sourceforge.net/pexpect.html

私が理解している限りでは、これはシステム コールのより洗練された「ランチャー」です。

于 2013-06-16T16:06:14.023 に答える
0

最後に、GObject.timeout_add を使用して解決し、スレッド化されたクラスの変数を使用してメッセージの状態を更新し、プロセスがいつ終了したかを.communicate()確認し、@johan-lundberg によって提案されたオプションを使用して解決しました

于 2013-06-16T21:30:15.130 に答える