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

标签 python multithreading bash

我有一个 python 程序,当我在线程中运行 bash 脚本并显示一些消息时,我希望进度条发出脉冲。

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

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

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

最佳答案

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

文档可以在这里找到: http://docs.python.org/2/library/subprocess.html#module-subprocess

你尝试了什么?

关于python - 在线程中运行 bash 脚本不阻塞主循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17126821/

相关文章:

Python,在使用Popen时更改当前的shell环境变量?

java - 将 python 列表返回给 Java

python - Google Assistant API,控制连接到 Google Home 的电灯开关

java - 多线程不比单线程快(简单循环测试)

linux - Bash echo 在字符串外带有 $ 字符

python - 获取Python中bash命令的所有输出

python - 如何在 sympy 中向扩展 `Poly` 类的类添加参数?

java - 没有打印语句,循环看不到其他线程更改的值

不调用 Thread.join() 时的 C++ 多线程异常

bash - 循环输入文件对