Tkinter indeterminate progress bar not running

倾然丶 夕夏残阳落幕 提交于 2019-12-12 06:23:27

问题


I'm currently creating a Tkinter Gui for Python 2.7 and having trouble working the progress bar. I need to load largish files into my program which takes some time, so I wanted to get a progress bar to show the user the program isn't frozen loading the files. Unfortunately my progress bar does not seem to update while loading files :( I've tried creating a new thread for the progress bar with no luck. So I'm wondering what do I need to do to get an indeterminate progress bar to run during a heavy function call?

What the relevant parts of my code looks like are:

import Tkinter as tk
import ttk as ttk
import pandas as pd
import tkFileDialog as tfgiag

self.pb = ttk.Progressbar(frame, orient=tk.VERTICAL, mode='indeterminate')
mynewdata = tfgiag.askopenfilenames(parent=root,title='Choose a file',filetypes=[('CSV files', '.csv')])
self.t = threading.Thread(target = self.pb.start)
self.t.start()  
#read in each CSV file selected by the user
for myfile in root.tk.splitlist(mynewdata): 
    foo = pd.read_csv(myfile)    
    self.data.appendMainData(foo)
self.pb.stop()

回答1:


Python "threads" are all still sort of locked together sequentially by what's called the GIL, global interpreter lock. It basically means that threads spawned from the same python process won't run in parallel like you want them to. Instead, they all fight for time on the main python process.

In your case, if there's an intensive process you're trying to monitor with once process, its probably hogging the GIL, and not releasing it to the thread.

One option: Try using a readline method, so it splits up the file input work enough to insert a progress bar update line.

openfile = open(filename, 'r')
for eachline in openfile.readlines():
    append_line(eachline)
    update_progressBar()

Another option that may be easier is to offload the csv opening to another process using python's multiprocessing module. This emulates the threads you're probably more used to. I'd kick off a new process that reads in the csv, and appends the lines to a queue. When it's done, append a sentinel value to the queue signalling its done, so the main process knows when to stop updating the progress bar and join the spawned process. Something like:

import Tkinter as tk
import ttk as ttk
import pandas as pd
import tkFileDialog as tfgiag
from multiprocessing import Process, Queue

self.pb = ttk.Progressbar(frame, orient=tk.VERTICAL, mode='indeterminate')
mynewdata = tfgiag.askopenfilenames(parent=root,title='Choose a file',filetypes=[('CSV files', '.csv')])

csvqueue=Queue(1) #A mp-enabled queue with one slot to results.
#read in each CSV file selected by the user
offloadedProcess=Process(target=csvread, args=(filename, outputqueue))
offloadedProcess.start()
procNotDone=False
while procNotDone:
    result = getNewResultFromQueue(outputqueue) #pesudo code
    update_ProgressBar() #<--- this should get hit more often now
    if result.isLastValue:
        offloadedProcess.join() #Join the process, since its now done
    else:
        csvresults.append(result)


def csvreadOffload(filename, outputqueue):
    for myfile in root.tk.splitlist(mynewdata): 
        foo = pd.read_csv(myfile)    
        if foo is not END:#Pesudo code here
            outputqueue.append(foo)
        else:
            outputqueue.append('Empty results')#pseudo code



回答2:


use self.frame.update_idletasks() after every self.pb.step(x) statement,where 'x' stands for the value by which progressbar's value increases



来源:https://stackoverflow.com/questions/18899440/tkinter-indeterminate-progress-bar-not-running

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!