Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cookbook GUI interface for a command-line script

I have a command-line Python script that works well to convert one sort of file into another given a few parameters and would now like to deploy this to some of my colleagues who may not know what a command line is.

I could work for hours trying to determine which Python GUI toolkit is "best", then learning how to do what I need, but it seems like this would have been done before.

Is there a relatively cook-book method to GUIify my program? Direction to either some sort of lesson/tutorial or an existing, documented, concise program would be excellent.

like image 813
Nick T Avatar asked Sep 18 '25 23:09

Nick T


2 Answers

Just a quick and simple example which may teach you enough wxPython to get going:

import wx
from subprocess import Popen, PIPE

class MainWindow(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        self.panel = wx.Panel(self)
        self.button = wx.Button(self.panel, label="Run!")
        self.command = wx.TextCtrl(self.panel)
        self.result = wx.TextCtrl(self.panel, style=wx.TE_MULTILINE)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.command, 0, wx.EXPAND)
        self.sizer.Add(self.button, 0, wx.EXPAND)
        self.sizer.Add(self.result, 1, wx.EXPAND)

        self.command.SetValue("dir")
        self.button.Bind(wx.EVT_BUTTON, self.CallCommand)

        self.panel.SetSizerAndFit(self.sizer)  
        self.Show()

    def CallCommand(self, e):
        p = Popen(self.command.GetValue(), shell=True, 
                  stdin=PIPE, stdout=PIPE, stderr=PIPE)
        r = p.communicate()
        self.result.SetValue(r[0])

app = wx.App(False)
win = MainWindow(None)
app.MainLoop()

To complete the example, following code runs command line in another thread and shows the result line by line:

import wx
from wx.lib.delayedresult import startWorker 
from subprocess import Popen, PIPE

class MainWindow(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        self.panel = wx.Panel(self)
        self.button = wx.Button(self.panel, label="Run!")
        self.command = wx.TextCtrl(self.panel)
        self.result = wx.TextCtrl(self.panel, style=wx.TE_MULTILINE)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.command, 0, wx.EXPAND)
        self.sizer.Add(self.button, 0, wx.EXPAND)
        self.sizer.Add(self.result, 1, wx.EXPAND)

        self.command.SetValue("dir")
        self.button.Bind(wx.EVT_BUTTON, self.CallCommand)

        self.panel.SetSizerAndFit(self.sizer)  
        self.Show()

    def CallCommand(self, e):
        startWorker(self.WorkCommandDone, self.WorkCommand)

    def WorkCommand(self):
        self.button.Disable()
        p = Popen(self.command.GetValue(), shell=True, 
                  stdin=PIPE, stdout=PIPE, stderr=PIPE)
        while True:
            line = p.stdout.readline()
            if line != '':
                wx.CallAfter(self.result.AppendText, line)
            else:
                break

    def WorkCommandDone(self, result):
        self.button.Enable()

app = wx.App(False)
win = MainWindow(None)
app.MainLoop()
like image 167
Fenikso Avatar answered Sep 21 '25 15:09

Fenikso


There are a few answers advocating wxpython. However, any toolkit will work for this project. Tkinter has the added benefit tha you and your collegues already have it installed and it is very easy to use.

That being said, the other toolkits are more-or-less equally easy to use but you might have to jump through a hoop or two to get them installed. If installation is not an issue it won't matter which one you pick.

Unfortunately, telling you how to "GUIfy" your program is hard since we know nothing about your app. Probably all it will involve is putting up a few labels and input widgets, then creating a button that collects all the data and then runs your program with the subprocess module.

like image 32
Bryan Oakley Avatar answered Sep 21 '25 15:09

Bryan Oakley