Найти - Пользователи
Полная версия: pygtk. Вывод консольного приложения в TextBuffer
Начало » GUI » pygtk. Вывод консольного приложения в TextBuffer
1
neol
Есть примерно такой код:
import gtk
from subprocess import Popen
from subprocess import PIPE

class Ping(gtk.Window):
def __init__(self):
gtk.Window.__init__(self)
self.connect('delete_event', self.delete_event)
self.box = gtk.VBox()
self.add(self.box)
self.ping = gtk.Button('Ping')
self.box.add(self.ping)
self.ping.connect("pressed",self.start_ping)
self.text = gtk.TextBuffer()
self.result = gtk.TextView(self.text)
self.result.set_editable(False)
self.box.add(self.result)
self.show_all()

def delete_event(self, widget, event, data=None):
gtk.main_quit()

def start_ping(self,event):
p = Popen(["/bin/ping","-c","4","ya.ru"],stdout=PIPE)
sts = p.communicate()[0]
self.text.set_text(sts)

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

if __name__ == '__main__':
main()
Приложение замирает, потом вываливается полный вывод ping.
Хочется, чтобы вывод появлялся в TextView построчно. В документации subprocess есть пример как передать вывод на вход другому приложению, а вот как реализовать такое - не нашел.
certanista
Разбить gtk.main() на итерации и в каждой читать из пайпа, если я правильно ухватил проблемму.
http://developer.gnome.org/doc/GGAD/sec-mainloop.html
gmorgunov
Можно использовать gtk.CList у которого есть метод append(). По нажатию на кнопку Ping получаете пинг, который добавляется в clist. Для получения статистики, если она нужна, добавьте кнопку endPing и выберете из listclist нужную информацию.
import gtk
from subprocess import Popen
from subprocess import PIPE
class Ping:
def __init__(self):
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_size_request(600, 400)
window.connect("destroy", gtk.main_quit)

vbox = gtk.VBox()
window.add(vbox)
vbox.show()
scrolled_window = gtk.ScrolledWindow()
scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
vbox.pack_start(scrolled_window, True, True, 0)
scrolled_window.show()

self.clist = gtk.CList(1)
scrolled_window.add(self.clist)
self.clist.show()

hbox = gtk.HBox()
vbox.pack_start(hbox, False, True, 0)
hbox.show()
button_ping = gtk.Button("Ping")
hbox.pack_start(button_ping, True, True, 0)
button_ping.connect("pressed", self.start_ping)
button_ping.show()
window.show()

def start_ping(self,data):
listclist=['']
p = Popen("ping -c 1 ya.ru",shell=True,stdout=PIPE)
listout=p.stdout.readlines()
firststring=listout[0]
listclist[0]=firststring.replace('\n',' ')
print listclist[0]
self.clist.append(listclist)

if __name__ == "__main__":
Ping()
gtk.main()
neol
gmorgunov
Можно использовать gtk.CList у которого есть метод append(). По нажатию на кнопку Ping получаете пинг, который добавляется в clist. Для получения статистики, если она нужна, добавьте кнопку endPing и выберете из listclist нужную информацию.
Спасибо, данный вариант пожалуй устроит.

Но исключительно из спортивного интереса хотелось бы разобратся как получить вывод консольного приложения построчно. Я это представляю примерно так: запускается процесс и stdout для него назначается некий питоновский класс, эмулирующий файловый объект, а из этого класса при вызове write строка передается в callback (или производятся какие-то действия). Вот я не представляю как подменить stdout. Или это совсем бред?
gmorgunov
neol
Но исключительно из спортивного интереса хотелось бы разобратся как получить вывод консольного приложения построчно. Я это представляю примерно так: запускается процесс и stdout для него назначается некий питоновский класс, эмулирующий файловый объект, а из этого класса при вызове write строка передается в callback (или производятся какие-то действия). Вот я не представляю как подменить stdout. Или это совсем бред?
Это не бред.:) Похожее уже обсуждалось, правда в PyQt4: http://python.su/forum/viewtopic.php?pid=37382#p37382.
neol
Нашел правильное решение: использовать модуль vte
Примерчик
import gtk
import vte

class Ping(gtk.Window):
def __init__(self):
gtk.Window.__init__(self)
self.connect('delete_event', self.delete_event)
self.box = gtk.VBox()
self.add(self.box)
self.ping = gtk.Button('Ping')
self.box.add(self.ping)
self.ping.connect("pressed",self.start_ping)
self.term = vte.Terminal()
self.box.add(self.term)
self.show_all()

def delete_event(self, widget, event, data=None):
gtk.main_quit()

def start_ping(self,event):
self.term.fork_command('ping',('ping','-c','4','ya.ru'))

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

if __name__ == '__main__':
main()
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB