csv文件读取的状态栏

时间:2012-07-02 15:07:43

标签: python csv tkinter python-2.7

编辑:答案如下。 self.progress.update_idletasks()是进度条更新的秘密握手。谢谢mgilson。

我目前正在处理一些有点大的csv文件(有时高达700Mb),并且需要一段时间(从网络驱动器中提取)。我希望能够为用户提供一些反馈作为流程的状态。这导致我进入ttk状态栏。我已经查看了尽可能多的示例,然后尝试将它们应用到我的程序中但没有成功。我认为我的问题是我使用for循环来读取我的csv文件,但这可能不是问题。我不知道。下面是我的代码如何工作的示例。

import csv
import Tkinter as tk
import ttk

class MAIN(tk.Frame):
    def __init__(self, master, *args, **kwargs):
        n=0
        self.filename = 'some.csv'
        tk.Frame.__init__(self, *args, **kwargs)
        frame=tk.Frame(master, **kwargs)
        frame.grid()
        getdata = tk.Button(frame, text='Get Data', command=self.csvget)
        getdata.grid(row=n)
        n+=1
        self.progress = ttk.Progressbar(frame, orient='horizontal',
                                        length =200, mode='determinate')
        self.progress.grid(row=n)
    def prog(self):
        self.progress['value']=0
        try: f=open(self.filename, 'rb')
        except: return
        read = csv.reader(f, delimiter=',')
        self.maxrows=0
        for row in read: self.maxrows+=1
        self.progress['maximum']=self.maxrows
    def csvget(self):
        try: f=open(self.filename, 'rb')
        except: return
        read = csv.reader(f, delimiter=',')
        q=0
        for row in read:
            if q%100==0: self.progress['value']=q
            elif q==self.maxrows: self.progress['value']=q
            ... do some stuff (read into lists etc.)...

root=tk.Tk()
app=MAIN(root)
app.mainloop()

好吧,结果比我想象的要长。我知道我正在读两次文件。 (我无法弄清楚如何以任何其他方式获取csv文件的长度,如果你有解决方案我很满意。)但我的问题的主要内容仍然是如何获得进度条到工作。在其当前配置中,一旦文件完成读取,它立即从零变为完全。建议?

编辑:在mgilson的帮助下,我的代码变得更好了。但是,我的状态栏仍然不会更新文件。我尝试过以下方法:

self.completed = tk.IntVar()
self.completed.set(0)
self.progress = ttk.Progressbar(self.frame, orient='horizontal', length=200,
                   mode='determinate', maximum=100, variable=self.completed)
#in the function now
fsize = os.path.getsize(self.filename)
for r,row in enumerate(read):
    q=float(f.tell())/float(fsize)*100 
    if r%100 ==0:
        self.completed.set(q)

此外,我不是仅仅致电self.completed,而是defq作为输入,然后将其放入self.completed。而且不是使用self.completed我在variable中摆脱了self.progress kwarg并且直接通过def回到调用kwarg'值'。同样尝试的是self.progress.configure(value = q),它的行为与其他行为一样。

所有这些尝试仅在文件完成后刷新栏。

如果我在读取数据的for循环之前修改了条的状态,但在同一def中,条形在文件读完之前不会更新。 (我尝试将其设置为50作为实验,一旦文件完成,它就从无到100%。)

1 个答案:

答案 0 :(得分:1)

你想要这样的东西:

if q%100==0: 
    self.progress['value']=float(q)/100
    self.progress.update_idletasks()

或者也许:

self.progress.configure(value=q)
self.progress.update_idletasks()

使用之前的版本,只要您阅读100行,进度条就会被填满。

另请注意,只有当程序控制返回到主循环时,进度条才会更新,除非您明确告知它(使用update_idletasks())。

如果没有两次阅读文件,可能可以使用file.tell(无保证 - 请告诉我,如果它不起作用,我会删除此建议):

fsize=os.path.getsize(filename)
...
q=f.tell()/fsize

如果这样可行,您可以将构造函数更改为:

self.progress = ttk.Progressbar(frame, orient='horizontal',
                                length =200, mode='determinate',maximum=1.)

和你的循环:

for i,row in enumerate(read):
    q=f.tell()/fsize
    if i%100==0: 
        self.progress['value']=q
        self.progress.update_idletasks()
    #do stuff
else:
    self.progress['value']=q
    self.progress.update_idletasks()

另一方面注意,拥有一个简单的try/except条款通常不是一个好主意。你通常想要:

try:
   #something
except SomeError: #IOError?  OSError? some combination of the two of them?
   #something else.

只捕获您知道如何处理的异常。