加快这个Python脚本的想法

时间:2013-12-13 16:27:08

标签: python treeview tkinter

我编写了一个程序,它可以遍历目录,将文件移动到存档中,并能够排除某些路径。它工作正常,但速度很慢。

我无法找到与ttk.Treeview中的项目进行高效交互的方法,因此它构建了一个树和一个字典,它使用Treeview中的索引作为键,目录名称作为值。

关于如何加快这一进程的任何想法?

现在,在一个合适大小的文件夹中构建目录树大约需要3分钟,而在测试模式下打印新位置需要3分钟。

我的代码:

import tkFileDialog, os, ttk, checkage, logging, shutil
from Tkinter import *
import profile

source = ''
dest = ''

#Build UI
class Master(Frame):

    def __init__(self, parent):
        Frame.__init__(self, parent)         
        self.parent = parent        
        self.initUI()

    def initUI(self):
        self.parent.title("pyRchive")
        self.pack(fill=BOTH, expand=1)

        lSrc = Label(self, text="Choose Source Directory")
        lSrc.grid(column = 0, row = 0, padx = 2, pady = 2, sticky=NW)
        eSrc = Entry(self, bd=5, width=50)
        eSrc.grid(column = 0, row = 0, padx = 5, pady = 5, sticky=SW)
        bSrc = Button(self, text="Browse...", command=lambda: choosedir(eSrc))
        bSrc.grid(column = 1, row = 0, padx = 5, pady = 5, sticky=SW)
        bAdd = Button(self, text="Add", command=lambda: buildTree(self))
        bAdd.grid(column = 0, row = 1, padx = 5, pady = 5, sticky=NW)
        lDest = Label(self, text="Choose Destination Directory")
        lDest.grid(column = 0, row = 2, padx = 5, pady = 5, sticky=NW)
        eDest = Entry(self, bd=5, width=50)
        eDest.grid(column = 0, row = 2, padx = 2, pady = 5, sticky=SW)
        bDest = Button(self, text="Browse...", command=lambda: choosedir(eDest))
        bDest.grid(column = 1, row = 2, padx = 2, pady = 5, sticky=SW)
        bExec = Button(self, text="Archive Files", command=lambda: archive(self))
        bExec.grid(column = 0, row = 3, padx = 2, pady = 5, sticky=NW)
        bDel = Button(self, text="Remove Directory", command=lambda: deldir(self))
        bDel.grid(column = 1, row = 9, padx = 5, pady = 5, sticky=SE)
        tree = ttk.Treeview(self, height=20)
        tree.column("#0", width=400)
        tree.grid(column = 2, row = 0, padx = 5, pady = 5, rowspan=10, sticky=NSEW)

        ysb = ttk.Scrollbar(orient=VERTICAL, command=tree.yview)
        tree['yscroll'] = ysb.set
        ysb.grid(in_=self, column = 3, row=0, sticky=NS, rowspan=10)
        rootlst = {}

        #Display Directory when bBrowse is pressed
        def choosedir(text):
            logging.info('Adding Directory to %s' %(text))
            rootfolder = tkFileDialog.askdirectory()
            text.insert(0, os.path.abspath(rootfolder))

        #Build the Directory Tree
        def buildTree(self):
            logging.info('Building Directory Tree')
            rootfolder = eSrc.get()
            global source
            source = rootfolder
            create_root(rootfolder)
            for root, dirs, files in os.walk(rootfolder):        
                for i in rootlst:
                    if os.path.split(root)[0] == rootlst[i]:
                        logging.info('Adding %s to directory tree' %(root))
                        rt = tree.insert(i, 'end', text='\\' + os.path.basename(root))
                        rootlst[rt] = root
                        break
            eSrc.delete(0, 'end')
            #print tree.get_children()

        #Make root level of tree
        def create_root(root):
            logging.info('Adding the root directory (%s) to the tree' %(root))
            rt = tree.insert('', 'end', text=root)
            rootlst[rt] = root

        #Archive the files in the selected directories
        def archive(self):
            logging.info('Starting Archive Process')
            dest = eDest.get()
            if os.path.isdir(source):
                for i in rootlst:                    
                    for fname in os.listdir(rootlst[i]):
                        oldname = os.path.join(rootlst[i], fname)
                        if os.path.isfile(oldname):
                            logging.info('fname is a file')
                            if checkage.check(oldname):
                                logging.info('fname is older than 3 years')
                                newname = oldname.replace(source, dest)
                                logging.info('Moving %s to %s' %(oldname, newname))
                                print newname

            else:
                pass
                #put a message box here for invalid Destination Directory

        #Remove Directories from tree
        def deldir(self):
            selected = tree.selection()
            sel = []
            for i in selected:
                path = rootlst[i]
                print 'Delete ', tree.item(i, 'text'), ' and all sub directories'
                print path

                tree.delete(i)
                for i in rootlst:
                    if rootlst[i].startswith(path):
                        sel.append(i)
                for i in sel:
                    del rootlst[i]
            for i in rootlst:
                print i

def main():
    logging.basicConfig(filename='pyRchive.log', format='%(asctime)s %(message)s',
                        datefmt='%m/%d/%Y %I:%M:%S %p', level=logging.INFO)
    logging.info('Starting Application')
    root = Tk()
    app = Master(root)
    root.mainloop()



if __name__ == '__main__':
    main()

1 个答案:

答案 0 :(得分:1)

不要使用os.walk;相反,使用os.listdir获取第一级条目, 然后构建您的树,并且只在您执行时按需(当用户选择目录时) 另一个os.listdir所需目录并显示其内容等

您根据用户的操作对目录内容进行延迟评估 而不是提前建立一个大结构。