Search code examples
python-3.xtkinteroperating-systemsys

Duplicate a string in Tkinter when redirecting output to a text field


I redirect all my output to the program text field in Tkinter and I wanted to add a date and time to the message:

class StdRedirector(object):
    def __init__(self, text_field):
        self.text_field = text_field

    def write(self, string):
        msg_time = datetime.now().strftime('%m-%d %H:%M:%S')
        self.text_field.configure(state='normal')
        self.text_field.insert('end', f'{msg_time} >> {string}')
        self.text_field.see('end')
        self.text_field.configure(state='disabled')


class App:
    def __init__(self):
        self.builder = pygubu.Builder()
        self.__init_ui()
        self.__init_callbacks()
        self.mainwindow.mainloop()

    def __init_ui(self):
        self.builder.add_from_file(path.join(base_dir, 'assets', 'app.ui'))
        self.mainwindow = self.builder.get_object('mainwindow')
        self.output_text_field = self.builder.get_object('output_text_field')
        sys.stdout = StdRedirector(self.output_text_field)
        sys.stderr = StdRedirector(self.output_text_field)

    def __init_callbacks(self):
        callbacks = {
            'update_balance_function': self.__update_balance
        }
        self.builder.connect_callbacks(callbacks)

    def __update_balance(self):
        print(True)

But the date line I added is duplicated:

error

As I understand it, the line is separated by the line separator \n and each substring is sent separately, including line break. Can I fix it somehow?


Solution

  • You can simply check whether the string argument in write() contains any meaningful content, e.g. using ìf string.strip():

    class StdRedirector(object):
        def __init__(self, text_field):
            self.text_field = text_field
    
        def write(self, string):
            self.text_field.configure(state='normal')
            if string.strip():  # add date before message
                msg_time = datetime.now().strftime('%m-%d %H:%M:%S')
                self.text_field.insert('end', f'{msg_time} >> {string}')
            else:  # simply insert string
                self.text_field.insert('end', string)
            self.text_field.see('end')
            self.text_field.configure(state='disabled')