Run an external Python script from wxPython GUI

Dear all,
I have been trying to figure out how I can execute a Python script from a GUI but with no luck. Searching the internet I have come across several ideas (threading, subprocess, etc…) but I do not seem to get it right. To illustrate what I need to do, below is a simple GUI that I have built.

############################################################
import wx

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE | wx.STAY_ON_TOP
        wx.Frame.__init__(self, *args, **kwds)
        self.SetSize((400, 300))
        self.SetTitle("TEST")

        self.panel_1 = wx.Panel(self, wx.ID_ANY)

        sizer_1 = wx.BoxSizer(wx.VERTICAL)

        grid_sizer_1 = wx.FlexGridSizer(5, 2, 1, 1)
        sizer_1.Add(grid_sizer_1, 1, wx.EXPAND, 0)

        label_1 = wx.StaticText(self.panel_1, wx.ID_ANY, "x")
        grid_sizer_1.Add(label_1, 0, wx.ALL, 5)

        self.text_ctrl_1 = wx.TextCtrl(self.panel_1, wx.ID_ANY, "")
        grid_sizer_1.Add(self.text_ctrl_1, 0, 0, 0)

        label_2 = wx.StaticText(self.panel_1, wx.ID_ANY, "y")
        grid_sizer_1.Add(label_2, 0, wx.ALL, 5)

        self.text_ctrl_2 = wx.TextCtrl(self.panel_1, wx.ID_ANY, "")
        grid_sizer_1.Add(self.text_ctrl_2, 0, 0, 0)

        grid_sizer_1.Add((0, 0), 0, 0, 0)

        self.button_1 = wx.Button(self.panel_1, wx.ID_ANY, "Save")
        self.button_1.SetFocus()
        grid_sizer_1.Add(self.button_1, 0, 0, 0)

        grid_sizer_1.Add((0, 0), 0, 0, 0)

        self.button_2 = wx.Button(self.panel_1, wx.ID_ANY, "Start")
        grid_sizer_1.Add(self.button_2, 0, 0, 0)

        grid_sizer_1.Add((0, 0), 0, 0, 0)

        self.button_3 = wx.Button(self.panel_1, wx.ID_ANY, "Stop")
        grid_sizer_1.Add(self.button_3, 0, 0, 0)

        self.panel_1.SetSizer(sizer_1)

        self.Layout()

        self.Bind(wx.EVT_BUTTON, self.OnClick_Save, self.button_1)
        self.Bind(wx.EVT_BUTTON, self.OnClick_Start, self.button_2)
        self.Bind(wx.EVT_BUTTON, self.OnClick_Stop, self.button_3)

    def OnClick_Save(self, event):  
        data = []
        x = float(self.text_ctrl_1.GetValue())
        data.append(x)
        y = float(self.text_ctrl_2.GetValue())
        data.append(y)

        event.Skip()

    def OnClick_Start(self, event):  
        # Button "Start" runs the module (script)
        event.Skip()

    def OnClick_Stop(self, event):  
        # Button "Stop" aborts the run
        event.Skip()

class MyApp(wx.App):
    def OnInit(self):
        self.frame = MyFrame(None, wx.ID_ANY, "")
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True

if __name__ == "__main__":
    Test = MyApp(0)
    Test.MainLoop()
################################################################

For a start, the external Python script I am trying to run from the above GUI is a sympy code:

################################################################
import sympy
from sympy import symbols, sin, cos, N

x, y = symbols('x, y')

z = N(sin(x) + cos(y))

print(z)
################################################################

What I am hoping to achieve is:

  1. Running the external script after entering the values of x and y in the text controls and clicking the ‘Save’ followed by the ‘Start’ buttons.
  2. Being able to abort the run by clicking the ‘Stop’ button.
  3. Writing the output (results of the calculation) to a text file (preferred method ) or to the GUI.

Please note that the real life scripts that I will be running will take from several minutes to possibly several hours to complete.

If it is of help, here are the details of what I am using: Python 3.8.5; wxPython 4.1.0 and MSW 10 64 bit.

Any help is highly appreciated.
Many thanks in advance.

omar

Well, apart from how to effect stopping you never do start
the external script as far as I can see ?

Karsten