Tkinter不确定进度条未运行

时间:2013-09-19 15:52:10

标签: python pandas tkinter progress-bar

我目前正在为Python 2.7创建一个Tkinter Gui,并且无法使用进度条。我需要将大量文件加载到我的程序中需要一些时间,所以我想获得一个进度条来向用户显示程序没有冻结加载文件。不幸的是我的进度条在加载文件时似乎没有更新:(我已经尝试为进度条创建一个新线程而没有运气。所以我想知道我需要做些什么来获得一个不确定的进度条来运行一个沉重的函数调用?

我的代码的相关部分是:

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()

2 个答案:

答案 0 :(得分:0)

Python“线程”仍然被所谓的GIL(全局解释器锁)依次锁定在一起。它基本上意味着从同一个python进程生成的线程不会像你想要的那样并行运行。相反,他们都在主要的python进程中争取时间。

在你的情况下,如果有一个密集的过程,你试图用一次进程监视,它可能会占用GIL,而不是释放到线程。

一个选项:尝试使用readline方法,因此它会将文件输入工作分开,足以插入进度条更新行。

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

另一个可能更容易的选择是使用python的multiprocessing模块将csv开放卸载到另一个进程。这模拟了您可能更习惯的线程。我将启动一个读取csv的新进程,并将这些行附加到队列中。完成后,将一个sentinel值附加到队列中,表示其已完成,因此主进程知道何时停止更新进度条并加入生成的进程。类似的东西:

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

答案 1 :(得分:0)

在每个self.frame.update_idletasks()语句后使用self.pb.step(x),其中'x'代表进度条值增加的值