我一直在尝试将取消按钮添加到进度条en pygtk但现在可以获得功能。它的功能是执行和脚本,输出中的每一行都计算它并添加到progressBar中。我的问题是如何取消该子进程,有没有办法?
def stop(self, widget):
print "cancelar"
os.killpg(self.p.pid, signal.SIGTERM) #=> not working
self.p.kill() #=> not working
count = 0
command = "script.sh"
self.p = subprocess.Popen(command, shell=True, bufsize=0, stdout=subprocess.PIPE, universal_newlines=True)
for line in iter(self.p.stdout.readline, ""):
count = count + 1
while gtk.events_pending():
gtk.mainiteration()
gobject.timeout_add(1000, self.update)
porcentaje = float(count) / float(1400)
print porcentaje
self.progress.set_text(str(int(porcentaje * 100)) + "%")
self.progress.set_fraction(porcentaje)
答案 0 :(得分:4)
以下示例应该执行您要求的所有操作(希望如此),它会在两个textview中打印长时间运行命令的输出,在stdout的顶部和stderr中打印。
您可以使用停止按钮终止进程,进度将停止脉冲。
与此同时,UI不应该在没有使用线程的情况下冻结,它也应该在Windows上工作(不太确定,但我很有信心)但是你必须在其他方面改变'du'。< / p>
它使用GTK3,所以带有内省的pygobject(你也应该使用它......)但是如果你真的想要使用PyGTK,它应该非常简单易用。
from gi.repository import Gtk, GLib
import os, signal
class MySpawned(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.set_default_size(600,600)
vb = Gtk.VBox(False, 5)
self.tw_out = Gtk.TextView()
sw = Gtk.ScrolledWindow()
vb.pack_start(sw, True, True, 0)
sw.add(self.tw_out)
self.tw_err = Gtk.TextView()
sw = Gtk.ScrolledWindow()
vb.pack_start(sw, True, True, 0)
sw.add(self.tw_err)
self.progress = Gtk.ProgressBar()
vb.pack_start(self.progress, False, True, 0)
bt = Gtk.Button('Run')
bt.connect('clicked', self.process)
vb.pack_start(bt, False, False, 0)
bt = Gtk.Button('Stop')
bt.connect('clicked', self.kill)
vb.pack_start(bt, False, False, 0)
self.add(vb)
self.set_size_request(200, 300)
self.connect('delete-event', Gtk.main_quit)
self.show_all()
def run(self):
Gtk.main()
def update_progress(self, data=None):
self.progress.pulse()
return True
def kill(self, widget, data=None):
os.kill(self.pid, signal.SIGTERM)
def process(self, widget, data=None):
params = ['du', '--si', '/']
def scroll_to_end(textview):
i = textview.props.buffer.get_end_iter()
mark = textview.props.buffer.get_insert()
textview.props.buffer.place_cursor(i)
textview.scroll_to_mark(mark, 0.0, True, 0.0, 1.0)
def write_to_textview(io, condition, tw):
if condition is GLib.IO_HUP:
GLib.source_remove(self.source_id_out)
GLib.source_remove(self.source_id_err)
return False
line = io.readline()
tw.props.buffer.insert_at_cursor(line)
scroll_to_end(tw)
while Gtk.events_pending():
Gtk.main_iteration_do(False)
return True
self.pid, stdin, stdout, stderr = GLib.spawn_async(params,
flags=GLib.SpawnFlags.SEARCH_PATH|GLib.SpawnFlags.DO_NOT_REAP_CHILD,
standard_output=True,
standard_error=True)
self.progress.set_text('Running du --si')
io = GLib.IOChannel(stdout)
err = GLib.IOChannel(stderr)
self.source_id_out = io.add_watch(GLib.IO_IN|GLib.IO_HUP,
write_to_textview,
self.tw_out,
priority=GLib.PRIORITY_HIGH)
self.source_id_err = err.add_watch(GLib.IO_IN|GLib.IO_HUP,
write_to_textview,
self.tw_err,
priority=GLib.PRIORITY_HIGH)
timeout_id = GLib.timeout_add(100, self.update_progress)
def closure_func(pid, status, data):
GLib.spawn_close_pid(pid)
GLib.source_remove(timeout_id)
self.progress.set_fraction(0.0)
GLib.child_watch_add(self.pid, closure_func, None)
if __name__ == '__main__':
s = MySpawned()
s.run()