2013-12-13 3 views
1

Я написал программу, которая идет по каталогу, перемещает файлы в архив, с возможностью исключения определенных путей. Он работает, но он медленный.Идеи ускорить этот скрипт Python

Я не мог найти способ эффективно взаимодействовать с элементами в 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() 
+0

Вы можете попытаться выяснить, что происходит медленно: ходить по каталогам или заполнять древовидную структуру. (Комментируйте строки, которые вставляются в дерево и видят, как изменяется время выполнения) –

+0

Благодарим вас за ответ. Я попробовал ваше предложение, и, похоже, это ходьба, требующая времени. Я полагаю, это означает, что я ничего не могу с этим поделать? Есть ли лучший способ создать дерево каталогов с возможностью удаления каталогов из списка? Ну, мне не обязательно удалять каталоги из списка, мне просто нужно исключить их из процесса «Архив» – n30r3b3l

+0

Вы можете измерить, где вы ДЕЙСТВИТЕЛЬНО потеряете время. Самый простой способ - поместить некоторый 't = time.time()' и напечатать 't-time()' где-то в решающих местах! И не стоит недооценивать накладные расходы самого заявления печати! для петель и длинных списков также возможны подозрения. Постарайтесь определить, где вы действительно теряете время, а затем возвращайтесь! Не стесняйтесь приспосабливать оригинальный вопрос (не меняйте его оригинальное направление), чтобы отразить процесс сужения! Хорошая охота! ;-) –

ответ

1

Не используйте os.walk; вместо этого, используйте os.listdir, чтобы получить первые записи уровня, затем построить свое дерево и только по требованию (когда пользователь выбирает каталог) вы выполняете другого os.listdir требуемого каталога и отображать его содержимое и т.д.

Вы сделать ленивая оценка содержимого каталога в зависимости от действий пользователя вместо того, чтобы сделать большую структуру заранее.

Смежные вопросы