在不阻塞主循环的线程中运行bash脚本

2024-10-04 11:22:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个python程序,当我在线程中运行bash脚本并显示一些消息时,它需要一个progressbar脉冲。在

当我单击一个按钮时,线程开始启动脚本,但是消息和进度条只有在线程完成时才会响应,只显示最后一条消息。在

在阅读时,我明白我在阻塞主循环,但我不知道如何解决这个问题。在

我的程序的简化代码,问题是当调用“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())

Tags: fromimportselfinfoeventgtkmainlocal
3条回答

最后用GObject.timeout_添加使用threaded类中的变量更新消息的状态,以知道进程何时完成,并使用@johanlundberg建议的.communicate()选项

如果使用subprocess.Popen,则使用.wait()等待返回的处理程序。您可以使用.poll()检查进程是否已完成[和退出代码],或者使用.communicate()与其交互(标准输入/输出)。在

文件如下: http://docs.python.org/2/library/subprocess.html#module-subprocess

你试过什么?在

我真的不确定这是否有用,但我建议您看看Pexpect模块:http://pexpect.sourceforge.net/pexpect.html

据我所知,它是一个更复杂的系统调用“启动器”。在

相关问题 更多 >