2016-06-02 2 views
1

Я пишу еще один сценарий очистки питона. Это заменяет очень старый сценарий bash множеством find -delete, которые занимают до 9 часов, чтобы очистить наш видеообъявление.Сценарий очистки с mutttiple условиями

Я знаю, что в Google есть много таких, как на стеке, так и на самом деле, но у меня есть еще несколько ограничений, которые заставили меня написать то, что я нашел плохой/неэффективный код.

рассмотрим следующую структуру: реж

/data/channel1/video_800/0001/somefile_800_001.ts
/data/channel1/video_800/0001/somefile_800_002.ts
/данные/channel1/video_800 /0002/somediffile_800_001.ts
/data/channel1/video_800/0002/somediffile_800_002.ts
/data/channel1/video_800.m3u8
/data/channel1/video_900/0001/someotherfile_900_001.ts
/Дат а/CHANNEL1/video_900/0002/afile_900_001.ts
/data/channel1/video_900/0003/bfile_900_001.ts
/data/channel1/video_900/0003/cfile_900_001.ts
/data/channel1/video_900.m3u8

/data/channel2/video_800/0001/againsomefile_800_001.ts
/data/channel2/video_800/0001/againsomefile_800_001.ts
/data/channel2/video_800.m3u8

/данных/sport_channel/video_1000/0001/somefile.ts /data/sport_channel/video_1000/0001/somefile2.ts

Первое, что меня интересует, это название канала, так как есть правило для канала * и одно для спорта *.

Во-вторых, это конец видеодисков, который равен битрейту ... 800, 900, 1000, поскольку они могут иметь разные дни хранения.

Завершение: Я разбираюсь во всем и удаляю файлы на основе битрейта и расширения.

Следующий код работает, но слишком сложный, и я уверен, что не очень питонический. Поскольку в этом случае мне больше всего нравится производительность, я уверен, что есть более эффективный способ сделать это. Stacking for loop in for loop - это не только плохой дизайн, но и получает меня «find_files» слишком сложный [mccabe] в моем pymode.

** Оставшись функции удалить из примера кода, но это просто обычная попытка: за исключением использования os.rmdir и os.remove

Я открыт для всех предложений для улучшения моего кода.

Спасибо!

#!/usr/bin/python 

import os 
import time 
import fnmatch 

path = '/data' 
debits_short = ['200', '700', '1000', '1300', '2500'] 
debits_long = ['400', '1800'] 

def find_files(chan_name, debits, duration): 

    time_in_secs = time.time() - (duration * 24 * 60 * 60) 

    # List channel 
    for channel in os.listdir(path): 

     # Match category channels 
     if fnmatch.fnmatch(channel, chan_name): 

      # Go through bitrates 
      for debit in debits: 

       # Channel path now the default search path 
       channel_path = path + channel 

       # Walk through channel path to match bitrate files 
       for root, dirs, files in os.walk(channel_path, topdown=False): 
        for filename in files: 

         # Remove files that contain _bitrate_ and end with ts 
         if '_' + debit + '_' in filename: 
          if filename.endswith('.ts'): 
           if os.path.isfile(os.path.join(root, filename)): 
            if os.stat(os.path.join(root, filename)).st_mtime <= time_in_secs: 
             remove(os.path.join(root, filename)) 

         # Remove playlist files that contain bitrate.m3u8 
         if filename.endswith(debit + '.m3u8'): 
          if os.path.isfile(os.path.join(root, filename)): 
           if os.stat(os.path.join(root, filename)).st_mtime <= time_in_secs: 
            remove(os.path.join(root, filename)) 

        # Remove empty dirs 
        for dir in dirs: 
         if not os.listdir(os.path.join(root, dir)): 
          remove(os.path.join(root, dir)) 


find_files('channel*', debits_long, 3) 
find_files('sport*', debits_short, 7) 
+0

Во-первых, хотя: [Flat лучше, чем вложенными.] (Https: //www.python.org/dev/peps/pep-0020 /) – C14L

ответ

1

Вот возможный подход:

import os 
import glob 
import time 


class Purge(object): 

    removable_extensions = ['ts', 'm3u8'] 

    def __init__(self, basedir, channel_pattern, debits, 
       older_than_days, test_mode=False): 
     self.basedir = basedir 
     self.channel_pattern = channel_pattern 
     self.debits = debits 
     self.older_than_secs = time.time() - 24*60*60*older_than_days 
     self.test_mode = test_mode # If `True`, do not delete files. 

    def delete_file(self, filepath): 
     try: 
      os.remove(filepath) 
     except OSError: 
      pass 

    def file_for_deletion(self, filepath): 
     # Return `True` if a file meets all conditions for deletion. 
     filename, ext = os.path.splitext(os.path.basename(filepath)) 
     condition_ext = ext[1:] in self.removable_extensions 
     condition_old = os.stat(filepath).st_mtime <= self.older_than_secs 
     condition_deb = any(
      '_{}_'.format(d) in filename or filename.endswith(d) 
      for d in self.debits 
      ) 
     return all((condition_ext, condition_old, condition_deb)) 

    def purge_channel(self, channel_dir): 
     for root, dirs, files in os.walk(channel_dir): 
      for name in files: 
       filepath = os.path.join(root, name) 
       if self.file_for_deletion(filepath): 
        print filepath 
        if not self.test_mode: 
         self.delete_file(filepath) 
      #TODO: delete empty directories here. 

    def purge(self): 
     channels = glob.glob(os.path.join(self.basedir, self.channel_pattern)) 
     for channel_dir in channels: 
      self.purge_channel(channel_dir) 


if __name__ == '__main__': 

    purge_job_info = dict(
     basedir=r'path/to/data', # All channel folders live here. 
     channel_pattern='channel*', # `glob` pattern. 
     debits=['400', '1800'], 
     older_than_days=7, 
     ) 

    p = Purge(**purge_job_info) 
    p.test_mode = True 
    p.purge() 
+0

Я сначала начал использовать класс, но я не настолько опытен в питоне, чтобы написать его самостоятельно, но я буду расшифровать это с большим вниманием. я получаю ... выглядит довольно хорошо. Если мне нужно больше «каналов» или битрейта, мне просто нужно инициализировать класс с помощью другой job_info? Mucho спасибо! – EBerth

+0

Добавлена ​​функция delete_dir плюс другие задания, и она быстро blazzing !!! Я попытаюсь воспроизвести модульный подход каждый раз для других скриптов. Он прост, но настолько эффективен. Вот почему я люблю python (даже если я все еще очень много учусь). Еще раз спасибо! – EBerth

+0

Добро пожаловать! – feqwix

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