Учимся отпускать (или как я научился жить с бомбой) ...
Спросите себя: чего именно вы боитесь, и как вы справитесь с этим, если это произойдет? В приведенном вами примере вы хотите избежать потери данных. Способ, которым вы справились с этим, заключается в поиске каждой комбинации условий, которые вы считаете ошибкой, и размещении огромного количества записей в ней. Все по-прежнему пойдет не так, и неясно, что большое количество журналов будет хорошим способом справиться с этим. Набросок того, чего вы пытаетесь достичь:
for each file in a tree
if file is below the root
move it into the root
if nothing went wrong
delete empty subtrees
Так что же может пойти не так в этом процессе? Ну, есть много способов, с помощью которых операции перемещения файлов могут прекратиться из-за базовой файловой системы. Можем ли мы перечислить их все и предоставить хорошие способы борьбы с ними? Нет ... но в целом вы будете иметь дело с ними одинаково. Иногда ошибка - это просто ошибка, независимо от того, что это такое.
Так что в этом случае, если возникает какая-либо ошибка, вы хотите отменить и отменить любые изменения. Вы решили это сделать, создав резервную копию и восстановив ее, если что-то пойдет не так. Но наиболее вероятной ошибкой является переполнение файловой системы, и в этом случае эти шаги могут завершиться ошибкой ... Хорошо, это достаточно распространенная проблема - если вы в какой-то момент беспокоитесь о неизвестных ошибках, как вы можете остановить свою работу? путь восстановления от неправильного?
Общий ответ - сначала убедитесь, что вы выполняете какую-либо промежуточную работу, а затем делаете один неприятный (возможно, атомарный) шаг. В вашем случае вам нужно перевернуть ваше восстановление вокруг. Вместо того, чтобы создавать копию в качестве резервной копии, создайте копию результата. Если все получится, вы можете поменять новый результат на старое оригинальное дерево. Или, если вы действительно параноик, вы можете оставить этот шаг для человека. Преимущество здесь в том, что если что-то пойдет не так, вы можете просто прервать и выбросить созданное вами частичное состояние.
Ваша структура становится:
make empty result directory
for every file in the tree
copy file into new result
on failure abort otherwise
move result over old source directory
Кстати, в вашем текущем скрипте есть ошибка, которая делает этот псевдо-код более очевидным: если у вас есть файлы с одинаковыми именами в разных ветвях, они будут перезаписывать друг друга в новой плоской версии.
Второй момент, касающийся этого псевдо-кода, заключается в том, что вся обработка ошибок находится в одном и том же месте (т. Е. Оборачивает каталог make new и рекурсивную копию в один блок try и перехватывает все ошибки после него), это решает исходную проблему вопрос о большом соотношении регистрации / проверки ошибок к фактическому рабочему коду.
backup_dirname = str(uuid.uuid4())
try:
shutil.mkdir(backup_dirname)
for root, dirs, files in os.walk(dirname, topdown=False):
for file in files:
full_filename = os.path.join(root, file)
target_filename = os.path.join(backup_dirname,file)
shutil.copy(full_filename, target_filename)
catch Exception, e:
print >>sys.stderr, "Something went wrong %s" % e
exit(-1)
shutil.move(back_dirname,root) # I would do this bit by hand really