Show terminal output in a gui window using python Gtk

前端 未结 3 2069
误落风尘
误落风尘 2021-02-10 15:31

I am developing a software and in that I want a window, that will display the output thrown by the terminal (like a package manager does ). Example, if i give the install comman

相关标签:
3条回答
  • 2021-02-10 15:44

    I've been trying to do this and really struggling. I couldn't get the first example working and moved quickly onto the 2nd.

    Using the 2nd example above (Using Label to display text) and found that this works fine with Python 2.7 but I'm trying to use Python3 and some things just don't work.

    I struggled for ages trying to convert to Python3 and had to change some of the imports and change gtk to Gtk which got it mostly working but the thing that really stumped me was due to Python3 using utf-8 codes. I finally got it working by modifying "the non_block_read" function changing the returned text from utf-8 to string and coping with the return None case.

    I hope this helps.

    For completeness I attach my working code:-

    #!/usr/bin/env python3
    import gi
    gi.require_version('Gtk', '3.0')
    
    from gi.repository import Gtk
    from gi.repository import GObject
    
    import os
    from subprocess import Popen, PIPE
    import fcntl
    
    wnd = Gtk.Window()
    wnd.set_default_size(400, 400)
    wnd.connect("destroy", Gtk.main_quit)
    label = Gtk.Label()
    label.set_alignment(0, 0)
    wnd.add(label)
    wnd.show_all()
    sub_proc = Popen("ping -c 10 localhost", stdout=PIPE, shell=True)
    sub_outp = ""
    
    
    def non_block_read(output):
        ''' even in a thread, a normal read with block until the buffer is full '''
        fd = output.fileno()
        fl = fcntl.fcntl(fd, fcntl.F_GETFL)
        fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
        op = output.read()
        if op == None:
            return ''
        return op.decode('utf-8')
    
    
    
    def update_terminal():
        label.set_text(label.get_text() + non_block_read(sub_proc.stdout))
        return sub_proc.poll() is None
    
    GObject.timeout_add(100, update_terminal)
    Gtk.main()
    
    0 讨论(0)
  • 2021-02-10 15:45

    If you are on Linux (as you state), something like this should work:

    import gtk 
    import gobject
    import pango
    import os
    from subprocess import Popen, PIPE
    import fcntl
    
    wnd = gtk.Window()
    wnd.set_default_size(400, 400)
    wnd.connect("destroy", gtk.main_quit)
    textview = gtk.TextView()
    fontdesc = pango.FontDescription("monospace")
    textview.modify_font(fontdesc)
    scroll = gtk.ScrolledWindow()
    scroll.add(textview)
    exp = gtk.Expander("Details")
    exp.add(scroll)
    wnd.add(exp)
    wnd.show_all()
    sub_proc = Popen("ping -c 10 localhost", stdout=PIPE, shell=True)
    sub_outp = ""
    
    
    def non_block_read(output):
        fd = output.fileno()
        fl = fcntl.fcntl(fd, fcntl.F_GETFL)
        fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
        try:
            return output.read().decode("utf-8")
        except:
            return ''
    
    
    def update_terminal():
        textview.get_buffer().insert_at_cursor(non_block_read(sub_proc.stdout))
        return sub_proc.poll() is None
    
    gobject.timeout_add(100, update_terminal)
    gtk.main()
    

    The nonblocking read idea is from here.

    Using a Label to display the text:

    import gtk 
    import gobject
    import os
    from subprocess import Popen, PIPE
    import fcntl
    
    wnd = gtk.Window()
    wnd.set_default_size(400, 400)
    wnd.connect("destroy", gtk.main_quit)
    label = gtk.Label()
    label.set_alignment(0, 0)
    wnd.add(label)
    wnd.show_all()
    sub_proc = Popen("ping -c 10 localhost", stdout=PIPE, shell=True)
    sub_outp = ""
    
    
    def non_block_read(output):
        ''' even in a thread, a normal read with block until the buffer is full '''
        fd = output.fileno()
        fl = fcntl.fcntl(fd, fcntl.F_GETFL)
        fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
        try:
            return output.read().decode("utf-8")
        except:
            return ''
    
    
    def update_terminal():
        label.set_text(label.get_text() + non_block_read(sub_proc.stdout))
        return sub_proc.poll() is None
    
    gobject.timeout_add(100, update_terminal)
    gtk.main()
    
    0 讨论(0)
  • 2021-02-10 16:05

    You can use the subprocess module and the os module to get back the terminal output.You can check this question.

    0 讨论(0)
提交回复
热议问题