Search code examples
loggingwxpython

wxPython: Create a log system


I have an application that calls another script when clicking on a button. On that script, I have some prints that I would like to display on a wx.TextCtrl widget on the application but I have no clue where to start.

This is an example of the script called:

#export.py

def exportData():
    #some code
    #Some prints that I would like to display on the application

And here is how I call the script from the application:

def loadData(self, event):
    from export import exportData
    exportData()

I have some questions:

  1. I assume that print won't work as a log, and I have to use some kind of logging system. Is that correct? I've tried to use log.write but I keep getting "log not defined error".
  2. Maybe calling exportData() directly from def loadData isn't the best way to proceed. If it's the case, what is the correct way?
  3. Finally, How can I display the prints/logs into the wx.TextCtrl widget of the application?

Don't hesitate if you need more information. Thank you in advance for your help.

EDIT

Here is a minimalist working example code of what I'm trying to do. Printing "This is my log" in the main.py TextCtrl.

# main.py
import wx, sys
import export

class Test(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id, "Frame aka Window", size=(300, 200))
        panel = wx.Panel(self)
        log = wx.TextCtrl(panel, style=wx.TE_MULTILINE|wx.TE_READONLY)

        button = wx.Button(panel, label="Export", pos=(80, 80), size=(120, 30))

        self.Bind(wx.EVT_BUTTON, self.export, button)

        mySizer = wx.BoxSizer(wx.VERTICAL)
        mySizer.Add(button, 0, wx.ALL | wx.ALIGN_CENTER, 5)
        mySizer.Add(log, 0, wx.ALL | wx.ALIGN_CENTER, 5)

        panel.SetSizer(mySizer)


    def export(self, event):
        from export import exportData
        exportData()


if __name__ == '__main__':
    app = wx.App()
    frame = Test(parent=None, id=1)
    frame.Show()
    app.MainLoop()

and the export file:

#export.py

def exportData():
    print("This is my log")

Solution

  • Firstly, congratulations on engineering the following statement import export, it makes me smile each time I see it.
    Are you attempting something like this?

    enter image description here

    Here is your amended code to do that:

    # main.py
    import wx, sys
    from export import exportData
    
    class Test(wx.Frame):
        def __init__(self, parent, id):
            wx.Frame.__init__(self, parent, id, "Frame aka Window", size=(300, 200))
            panel = wx.Panel(self)
            self.log = wx.TextCtrl(panel, style=wx.TE_MULTILINE|wx.TE_READONLY, size=(180,100))
            button = wx.Button(panel, label="Export")
            self.Bind(wx.EVT_BUTTON, self.export, button)
            mySizer = wx.BoxSizer(wx.VERTICAL)
            mySizer.Add(button, 0, wx.ALL | wx.ALIGN_CENTER, 5)
            mySizer.Add(self.log, 0, wx.ALL | wx.ALIGN_CENTER, 5)
            panel.SetSizer(mySizer)
    
        def export(self, event):
            exportData(parent=self)
    
    if __name__ == '__main__':
        app = wx.App()
        frame = Test(parent=None, id=1)
        frame.Show()
        app.MainLoop()
    

    and the export.py

    import time
    import wx
    
    def exportData(parent=None):
        if not parent:
            return
        log = []
        print("This is my log")
        parent.log.write("This is my log\n")
        #solely for the purpose of illustrating updates in real time use sleep between updates
        # and yield to the gui main loop
        # in real time operation remove the sleep commands
        wx.Yield()
        time.sleep(1)
        print("Log line 2")
        parent.log.write("Log line 2\n")
        wx.Yield()
        time.sleep(1)
        print("Log line 3")
        parent.log.write("Log line 3\n")
        wx.Yield()
        time.sleep(1)
        print("Export data has concluded")
    

    All that is happening here is we pass the parent to the function, which allows the updates to occur in real-time. The call to Yield passes control momentarily back to the wx.App.MainLoop for the update to be seen occurring, otherwise, although the update occurred, the result isn't seen, until the MainLoop takes back control.