Program freezing during the execution of a function in Tkinter
Asked Answered
M

1

9

I've created a little GUI for one of my scripts. All is working well.

When I click on one Button, it launches a big function that is parsing a lot of data from some websites.

But once I've clicked on the Button, the program Freezes until the function is run entirely. All is working fine, but why is my GUI freezing during the execution of the function. I'd like to print a little progress bar, but it's not possible.

Here is part of the program:

    self.Button1 = Button(self.MENU, text="IELTS", command=self.My_Command)
    self.Button1.grid(row=0, column=0,sticky=W+E)

def My_Command(self):

    ## HERE WE LAUNCH THE FUNCTION
    Module_1.main() # My Big Function from another file

    self.Button1.config(text="DONE")

I can't do/print anything durint the execution of Module_1.main() ... the GUI is totally freezed.

The Module_1.main() function is a threaded parser (parsing some data from two websites), it takes generally 2 minutes to be ran. If someone have an idea to be able to interact with the program during the 2 minutes needed for the execution of this function, it would be very helpful.

Maniac answered 1/6, 2012 at 9:20 Comment(4)
This may be a better topic for codereview.stackexchange.com. Sounds like your parsing should be in a separate thread and its not (even though you say its threaded) I think more context is necessary to answer the question, can you provide a link to the complete code on github, ideone.com, or pastebin.com?Rikkiriksdag
Badly I don't have any access to the code right now but you give me kind of an answer. The parser is threaded but but function is not. So I need to put in two separate threads the function and the GUI .. ! Thx ;)Maniac
@Brady: no more context is needed. This is a well known Tkinter anti-pattern.Sceptre
@BryanOakley, I figured as much, thanksRikkiriksdag
S
7

Tkinter is single threaded. Screen updates happen on each trip through the event loop. Any time you have a long running command you are preventing the event loop from completing an iteration, thus preventing the processing of events, thus preventing redraws.

Your only solution is a) use a thread for the long running command, b) use a process for the long running command, or c) break the command up into small chunks that each can be run in a few ms so you can run one chunk during subsequent iterations of the event loop. You have one other solution which is to call the update_idletasks method of a widget periodically, but that's more of a workaround than a fix.

Bear in mind that Tkinter is not thread safe, so using threads requires extra care. You can only call methods on widgets from the main thread, which means other threads must communicate with the main thread via a thread-safe queue.

Sceptre answered 1/6, 2012 at 10:55 Comment(2)
Thank you so much for your answer ! This is so much clear now. I'm gonna try to use a thread for the long running command. Thank you very much :-) (Btw, what is the B) solution, using a process? )Maniac
Hum, one more question (sorry for that) --> pastebin.com/yEGb8MuT Here is the function I'd like to execute with a click on a button ... But I'd like this function to work in "background" of Tkinter. I'm quite discovering Tkinter so if you can put me on a good track, It should be awesome. As you can see this function is actually threaded ... so are you sure that I can thread Tkinter & The Function ?Maniac

© 2022 - 2024 — McMap. All rights reserved.