#python #recursion
#python #рекурсия
Вопрос:
Я пишу скрипт для рекурсии по всем каталогам и подкаталогам начальной папки, но я сталкиваюсь с ошибками памяти (ошибка есть MemoryError
). Я предполагаю, что, возможно, мой data_dicts
список становится слишком большим, но я не уверен. Любые советы будут оценены.
import os
# example data dictionary
data_dict = {
'filename': 'data.csv',
'folder': 'R:/',
'size': 300000
}
def get_file_sizes_folder(data_dicts, starting_folder):
# Given a list of file information dictionaries and a folder, iterate over the files
# in the folder to get their information and append it to the list.
# Also recurse through subdirectories
for entry in os.scandir(starting_folder):
if not entry.name.startswith('.'):
if entry.is_file():
size = entry.stat().st_size
filename = entry.name
folder = os.path.dirname(entry.path)
temp_dict = {'filename': filename, 'size': size, 'folder': folder}
data_dicts.append(temp_dict.copy())
else:
print(entry.path)
data_dicts.extend(get_file_sizes_folder(data_dicts, entry.path))
return data_dicts
d = get_file_sizes_folder([], 'R:/')
Комментарии:
1. почему вы не используете
os.walk
?
Ответ №1:
Вы не должны указывать data_dicts
в качестве аргумента свою функцию get_file_sizes_folder()
. Это приведет к появлению множества дубликатов ваших записей со скоростью, которая, вероятно, почти факториальная. Неудивительно, что на вашем компьютере очень быстро заканчивается память!
Вместо этого используйте только starting_folder
в качестве аргумента и просто создайте новый список data_dicts
в первой строке вашей функции, например:
def get_file_sizes_folder(starting_folder):
# Given a list of file information dictionaries and a folder, iterate over the files
# in the folder to get their information and append it to the list.
# Also recurse through subdirectories
data_dicts = []
for entry in os.scandir(starting_folder):
if not entry.name.startswith('.'):
if entry.is_file():
size = entry.stat().st_size
filename = entry.name
folder = os.path.dirname(entry.path)
temp_dict = {'filename': filename, 'size': size, 'folder': folder}
data_dicts.append(temp_dict)
else:
print(entry.path)
data_dicts.extend(get_file_sizes_folder(entry.path))
return data_dicts
Ответ №2:
Вы вообще не должны выполнять рекурсию. Использование os.walk
Пример:
def get_file_sizes_folder(starting_folder):
data_dicts = list()
for root, _, files in os.walk(starting_folder):
data_dicts.extend({
'filename': f,
'size': os.path.getsize(os.path.join(root, f)),
'folder': root,
} for f in files)
return data_dicts
d = get_file_sizes_folder('R:/')
Комментарии:
1. Спасибо. Однако у меня есть несколько вопросов. Вы указываете
_
в качестве параметра, но я не вижу, чтобы вы его использовали. Кроме того, я заметил, что вы используете какое-то понимание списка, но у вас нет заключающих скобок, например:[{} for f in files]
. Не могли бы вы, пожалуйста, объяснить это?2. Это
_
потому, что мне не нуженfolders
параметр команды. Принято использовать подчеркивание для нежелательных / неиспользуемых параметров. Понимание списка — это не понимание списка, это выражение генератора. Я рекомендую вам протестировать его и убедиться, что поведение является ожидаемым.