Python csv文件读取的状态栏

Python csv文件读取的状态栏,python,csv,tkinter,python-2.7,Python,Csv,Tkinter,Python 2.7,编辑:答案如下self.progress.update_idletasks()是更新进度条的秘密握手。谢谢你,麦吉尔森 我目前正在处理一些较大的csv文件(有时高达700Mb),这需要一段时间(从网络驱动器中提取)。我希望能够给用户一些反馈作为进程的状态。这将我引导到ttk状态栏。我看了尽可能多的例子,然后试图将它们应用到我的程序中,但没有成功。我想我的问题是我正在使用for循环来读取我的csv文件,但这可能不是问题所在。我不知道。下面是我的代码如何工作的示例 import csv import

编辑:答案如下
self.progress.update_idletasks()
是更新进度条的秘密握手。谢谢你,麦吉尔森

我目前正在处理一些较大的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
而是制作了一个
def
,将
q
作为输入,然后将其放入
self.completed
。另外,我没有使用
self.completed
而是在
self.progress
中去掉了
变量
kwarg,并返回到直接调用和通过
def
调用kwarg'value'。还尝试了
self.progress.configure(value=q)
,其行为与其他操作相同

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


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

您想要类似于:

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

self.progress.configure(value=q)
self.progress.update_idletasks()
对于上一个版本,只要你读了100行,进度条就会被填满

另外请注意,除非您明确地告诉进度条,否则只有在程序控制返回到mainloop时才会更新进度条(使用
update\u idletasks()

至于不读取文件两次,您可以使用
文件。告诉
(不保证——如果不起作用,请告诉我,我将删除此建议):

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

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.

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

是否需要类似以下内容:

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

self.progress.configure(value=q)
self.progress.update_idletasks()
对于上一个版本,只要你读了100行,进度条就会被填满

另外请注意,除非您明确地告诉进度条,否则只有在程序控制返回到mainloop时才会更新进度条(使用
update\u idletasks()

至于不读取文件两次,您可以使用
文件。告诉
(不保证——如果不起作用,请告诉我,我将删除此建议):

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

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.

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

我正在应用您的异常。在循环调用中,我如何调用一行中的第5个元素?还是排[4]?我以前从未见过这种格式。@deadstump。对<代码>枚举
只需环绕任何迭代器并返回索引,然后返回元素。在本例中,元素是行(列表),因此您可以使用变量
row
,就像您以前使用它一样。文件大小的边界非常有效,可以避免我打开文件两次。但是,进度条在获取文件时仍然不会更新其自身。我做了一个小实验,试图在调用开始时让条形图重置它自己
['value']=0
。没有。在不同的def调用中,是否存在阻止刷新条的因素?@deadstump——此类上的文档非常稀少,因此很难确定。不管怎样,我添加了另一个建议,可能会有帮助…@deadstump——最后一次尝试。尝试在更新后立即添加
self.progress.update\u idletasks()
。否则,我试着滚动我自己的状态栏,你可以自由使用。我正在努力应用你的状态栏。在循环调用中,我如何调用一行中的第5个元素?还是排[4]?我以前从未见过这种格式。@deadstump。对<代码>枚举
只需环绕任何迭代器并返回索引,然后返回元素。在本例中,元素是行(列表),因此您可以使用变量
row
,就像您以前使用它一样。文件大小的边界非常有效,可以避免我打开文件两次。但是,进度条在获取文件时仍然不会更新其自身。我做了一个小实验,试图在调用开始时让条形图重置它自己
['value']=0
。没有。在不同的def调用中,是否存在阻止刷新条的因素?@deadstump——此类上的文档非常稀少,因此很难确定。不管怎样,我添加了另一个建议,可能会有帮助…@deadstump——最后一次尝试。尝试添加
sel