2013-01-17 36 views
1

我在寫一個腳本,需要從我們公司的數據庫中刪除大量的電影/媒體文件。我正在開發Mac和Python環境,這兩者對我來說都是新手。我試圖儘可能地提高彈性,因爲它可能會破壞當前正在生產的所有項目的數據庫,而不是已經退役的舊項目的數據庫。截斷文件並在Python中登錄

想知道,如果有任何嚴重的邏輯瑕疵,如果我登錄權等等和任何其他建議,使盡可能健壯和小心越好越好。

import os.path 
import shutil 
import datetime 
import logging 

root_path = "blah" 
age_in_days = 2 
truncate_size = 1024 


class TruncateOldFiles(): 
    def delete_files(root_path): 
     if os.path.exists(root_path): 
      for dirpath, dirnames, filenames in os.walk(root_path): 

       for file in filenames: 
        current_path = os.path.join(dirpath, file) 
        file_modified_time = datetime.date(os.path.getmtime(current_path)) 

        if ((datetime.datetime.now() - file_modified_time) > datetime.timedelta(days = age_in_days)): 
         count += 1 


       if count == len(files) and not os.path.isfile("donotdelete.txt"): 
        for file in filenames: 
         try: 
          with open (file, 'w+') as file: 
           file.truncate(1024) 

          log() 

         except IOError: 
          pass 



    def log(): 
     format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' 
     logging.basicConfig(filename='myapp.log', level=logging.INFO, format = format) 
     logging.info('Starting to truncate all files...') 

此外,我只能夠在終端編譯這個,但不知道如何從它調試邏輯錯誤。我習慣於在IDE中使用C++和Java進行編碼,在這裏我使用的Xcode對於我的開發風格似乎不太有利。

謝謝。

回答

0

我不確定提到的數據庫在哪裏發揮作用,你似乎只是在文件系統中處理文件名。

  • 您正在使用os.path.isfile()其中如果存在的東西是一個文件(而不是目錄,鏈接等),我只會用於測試。它返回假(如果名稱不存在於文件系統中,我必須查看),因此它可以工作。但是我會預料它會拋出一個IOError。 我的建議是用os.path.exists()代替。

  • 要小心與比較date()datetime(),它們是不一樣的。並從時間戳得到datetime()使用.fromtimestamp

  • 我希望你認識到腳本總是在你啓動腳本的目錄中尋找'donotdelete.txt'。 os.walk不會執行os.chdir。如果這不是你想要的(並有一個在每個目錄有donotdelete.txt爲某些特定的目錄一種保障什麼不能截斷,您應該測試os.path.exists(os.path.join(dirpath, 'donotdelete.txt'))

  • len(files)?你的意思是len(filenames),看看是否所有在目錄中的文件符合年齡比較count

  • 您正確地構建從dirpath一個current_path,並在for循環,你測試年齡filename。在for循環截斷你只需要使用file,這會嘗試在當前目錄中打開。

  • 您製作的是舊式類我總是會做出新的類new style

    類TruncateOldFiles(對象): ....

  • 你應該在每個self參數方法,那麼你可以調用logself.log(),因爲除非你做TruncateOldFiles.log()

  • 您的代碼將無法正常工作,我不知道在哪裏的日誌格式信息得到填補從。它寫(修正如何log()被調用時,只有線starting to truncate .....它會截斷沒有附加信息的每個文件之後。

  • 數將不會被初始化,只是遞增,你需要做的count = 0

  • 我會通過在根路徑中,days和truncate size是創建類的參數,後兩者可能是默認值。

  • 對於這種破壞性的不可逆操作,我添加了一個參數給類創建,以便能夠擁有除了日誌以外,它不需要做任何事情,也許這就是t他測試donotdelete.txt是爲了但不記錄任何東西,所以你在日誌中沒有跡象表明該程序會做什麼。

  • 對於許多類我有一個詳細的說法,與發現錯誤幫助,這是一個互動的運行,從日誌不同

  • 你有1024硬編碼,而不是使用truncate_size,和你打開和截斷小於truncate_size的文件是不必要的。

  • 您使用file(蟒關鍵字)作爲變量名都在for循環以及在with語句,它可能工作,但它是不是很好的風格和必然導致的問題,當你擴展代碼在for循環中。

我的班級會更喜歡(但log()仍然需要固定):

class TruncateOldFiles(): 
    def __init__(self, age_in_days=2, truncate_size=1024, 
       verbose=0, for_real=True): 
     self._age = datetime.timedelta(days = age_in_days) 
     self._truncate_size = truncate_size 
     self._verbose = verbose 
     self._for_real = for_real 

    def delete_files(self, root_path): 
     if not os.path.exists(root_path): 
      if self._verbose > 1: 
       print 'root_path', self._root_path, 'does not exists' 
      return 
     for dirpath, dirnames, filenames in os.walk(root_path): 
      count = 0 
      for filename in filenames: 
       current_path = os.path.join(dirpath, filename) 
       file_modified_time = datetime.datetime.fromtimestamp(os.path.getmtime(current_path)) 
       if self._verbose > 0: 
        print file_modified_time, current_path 
       if ((datetime.datetime.now() - file_modified_time) > self._age): 
        count += 1 
      if count == len(filenames) and not os.path.exists(os.path.join(dirpath, "donotdelete.txt")): 
       for filename in filenames: 
        current_path = os.path.join(dirpath, filename) 
        if os.path.getsize(current_path) <= self._truncate_size: 
         if self._verbose > 0: 
          print 'not big enough:', current_path 
         continue 
        try: 
         if self._verbose > 0: 
          print 'truncating:', file 
         if self._for_real: 
          with open (current_path, 'w+') as fp: 
           fp.truncate(self._truncate_size) 
         self.log() 
        except IOError: 
         pass 

    def log(self): 
     format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' 
     logging.basicConfig(filename='myapp.log', level=logging.INFO, format = format) 
     logging.info('Starting to truncate all files...') 

和代碼來測試這一點:

tof = TruncateOldFiles(verbose=1, for_real=False) 
tof.delete_files('blah')