gobject and subprocess.Popen to communicate in a GTK GUI
I am trying to use a gobject to allow communication between a Popen process and a GTK GUI.

Inspired by this:
https://pygabriel.wordpress.com/2009/07/27/redirecting-the-stdout-on-a-gtk-textview/#comment-156

I implemented something similar to this:

http://hartree.altervista.org/files/command-textview.py

but I noticed that the gobject uses lots of CPU cycle even once the Popen process is terminated. Just run the scrip above and watch the Ubuntu System Monitor.

After some work with "pty" I came up with this:

    import gtk,pygtk
    import subprocess
    import gobject
    import pty, os, time
    
    class CommandTextView(gtk.TextView):
        def __init__(self):
            super(CommandTextView,self).__init__()
            self.master, self.slave = pty.openpty()
            gobject.io_add_watch(os.fdopen(self.master), gobject.IO_IN, self.write_to_buffer)
            self.proc = None
    
        def run(self, w, cmd):
            if self.proc == None or self.proc.poll() != None: # poll()=None means still running
                self.proc = subprocess.Popen(cmd.split(), shell=True, stdout=self.slave, stderr=self.slave)
          
        def stop(self,w):
            if type(self.proc) is subprocess.Popen:
                self.proc.kill()
                while self.proc.poll() == None:
                    time.sleep(0.1)
                self.proc = None
    
        def write_to_buffer(self, fd, condition):
            if condition == gobject.IO_IN:
                char = fd.readline()
                print 'adding:',char    
                buf = self.get_buffer()
                buf.insert_at_cursor(char)
                return True
            else:
                return False
    
    def test():
        win=gtk.Window()
        vbox = gtk.VBox(False, 0)
        win.set_size_request(300,300)
        win.connect('delete-event',lambda w,e : gtk.main_quit())
        ctv=CommandTextView()
        bt1 = gtk.Button('Run')
        bt2 = gtk.Button('Stop')
        vbox.pack_start(ctv)
        vbox.pack_end(bt2,False,False)
        vbox.pack_end(bt1,False,False)
        win.add(vbox)
        
        bt1.connect("clicked", ctv.run, 'ls -la')
        bt2.connect("clicked", ctv.stop)
        win.show_all()
        gtk.main()
    
    if __name__=='__main__': test()

The questions I have are:

 - is pty a good idea? Can it be used for Windows too?

 - is it possible to avoid using pty and just use stdout and not have the high CPU usage problem?

 - if you run this scrip the first time it seems to buffer the txt output and give an incomplete output.

Thank you for the help


gobject and subprocess.Popen to communicate in a GTK GUI
===

I am trying to use a gobject to allow communication between a Popen process and a GTK GUI.

Inspired by this:
https://pygabriel.wordpress.com/2009/07/27/redirecting-the-stdout-on-a-gtk-textview/#comment-156

I implemented something similar to this:

http://hartree.altervista.org/files/command-textview.py

but I noticed that the gobject uses lots of CPU cycle even once the Popen process is terminated. Just run the scrip above and watch the Ubuntu System Monitor.

After some work with "pty" I came up with this:

    import gtk,pygtk
    import subprocess
    import gobject
    import pty, os, time
    
    class CommandTextView(gtk.TextView):
        def __init__(self):
            super(CommandTextView,self).__init__()
            self.master, self.slave = pty.openpty()
            gobject.io_add_watch(os.fdopen(self.master), gobject.IO_IN, self.write_to_buffer)
            self.proc = None
    
        def run(self, w, cmd):
            if self.proc == None or self.proc.poll() != None: # poll()=None means still running
                self.proc = subprocess.Popen(cmd.split(), shell=True, stdout=self.slave, stderr=self.slave)
          
        def stop(self,w):
            if type(self.proc) is subprocess.Popen:
                self.proc.kill()
                while self.proc.poll() == None:
                    time.sleep(0.1)
                self.proc = None
    
        def write_to_buffer(self, fd, condition):
            if condition == gobject.IO_IN:
                char = fd.readline()
                print 'adding:',char    
                buf = self.get_buffer()
                buf.insert_at_cursor(char)
                return True
            else:
                return False
    
    def test():
        win=gtk.Window()
        vbox = gtk.VBox(False, 0)
        win.set_size_request(300,300)
        win.connect('delete-event',lambda w,e : gtk.main_quit())
        ctv=CommandTextView()
        bt1 = gtk.Button('Run')
        bt2 = gtk.Button('Stop')
        vbox.pack_start(ctv)
        vbox.pack_end(bt2,False,False)
        vbox.pack_end(bt1,False,False)
        win.add(vbox)
        
        bt1.connect("clicked", ctv.run, 'ls -la')
        bt2.connect("clicked", ctv.stop)
        win.show_all()
        gtk.main()
    
    if __name__=='__main__': test()

The questions I have are:

 - is pty a good idea? Can it be used for Windows too?

 - is it possible to avoid using pty and just use stdout and not have the high CPU usage problem?

 - if you run this scrip the first time it seems to buffer the txt output and give an incomplete output.

Thank you for the help

