Эффективное сканирование диска с использованием рекурсии в Python - PullRequest
3 голосов
/ 09 июля 2020

Исходный вопрос:

Я пытаюсь рекурсивно сканировать каталоги, чтобы получить занятый размер диска и сведения для каждого файла и папки, используя приведенный ниже код. Приведенный ниже код работает отлично, но мне нужен совет по повышению его эффективности, чтобы сканировать диски, которые имеют 200 ГБ или более занятого пространства / данных. Результаты тестирования для диска с 5,49 ГБ (244 169 файлов и 34 253 папки) занимаемого пространства следующие:

  1. Если код запускается без операции добавления списка, сканирование диска занимает примерно 8 минут. что не очень эффективно :
    server_size = scanSlot('D:\\New folder')
    

    Я пытался оптимизировать код, используя следующие методы:

    1. Python библиотека numba , это не работает, так как numba не имеет реализации для используемой библиотеки os.
    2. Попытка преобразовать код в Cython , но не совсем уверен, поможет ли это

    Список добавлен операцию нельзя упускать из виду, поскольку детали в этом path_list необходимы для дальнейшего анализа.

    Обновления:

    Согласно предложению @ triplee и с помощью орудия entation здесь Я реализовал сканирование каталогов с помощью os.walk (), и очевидно, что это намного быстрее (19,6 ГБ с 2,75,559 файлов, 38,592 папок, сканированных за 20 минут при выполнении ввода-вывода в файл журнала для каждого каталог файлов). Код выглядит следующим образом:

    К СВЕДЕНИЮ: ЭТО ЕЩЕ ТЕСТИРУЕМ

    def scanSlot(path):
        total_size = 0
        global path_list
        for dirpath, dirnames, filenames in os.walk(path):
                    
            for f in filenames:
                fp = os.path.join(dirpath, f)
                # skip if it is symbolic link
                if not os.path.islink(fp):
                    # logging.info('Filename:'+str(fp)+'Size:'+str(os.path.getsize(fp)))
                    file_stat = os.stat(fp)
                    path_list.append((f,fp,file_stat.st_mode,file_stat.st_ino,file_stat.st_dev,file_stat.st_nlink,file_stat.st_uid,file_stat.st_gid,os.path.getsize(fp),
                                           datetime.fromtimestamp(file_stat.st_atime),datetime.fromtimestamp(file_stat.st_mtime),datetime.fromtimestamp(file_stat.st_ctime),"file"))
                    total_size += os.path.getsize(fp)
    
    
        return total_size
    
    if __name__ == "__main__":
        logging.info('>>> Start:' + str(datetime.now().time()))
    
        # So basically run os.walk() for a drive and then do so for all directories present in it
    
        for dirpath, dirnames, filenames in os.walk('F:\\'):
    
            for f in dirnames:
                fp = os.path.join(dirpath, f)
                dir_size = scanSlot(fp)
                file_stat = os.stat(fp)
                logging.info('Dirname:'+str(fp)+'Size:'+str(dir_size))
                path_list.append((f,fp,file_stat.st_mode,file_stat.st_ino,file_stat.st_dev,file_stat.st_nlink,file_stat.st_uid,dir_size,
                                           datetime.fromtimestamp(file_stat.st_atime),datetime.fromtimestamp(file_stat.st_mtime),datetime.fromtimestamp(file_stat.st_ctime),"dir"))
               
               
        logging.info('>>> End:' + str(datetime.now().time()))
    

    Дополнительные вопросы:

    • Как сделать это еще более эффективным / быстрым, изначально я думал о многопроцессорности, как о параллельном сканировании 3 дисков в 3 разных процессах.

    Ссылки:

    Объяснение для follow_symlinks также можно найти по ссылкам выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...