Я вижу, что вы уже написали большую часть кода, но в настоящее время он содержит довольно много ошибок:
- Код имеет неправильный отступ, что делает его недействительным кодом Python.
- Некоторые операторы импорта отсутствуют (например, для
shutil
).
- Вы имеете в виду неопределенные переменные (например,
source
).
Если я копирую и вставляю ваш код в мою среду IDE, я получаю 26 ошибок от pep8
и pylint
, и после исправления ошибки отступа я получаю 49 ошибок. Это заставляет меня задуматься, действительно ли это ваш код или вы сделали ошибки копирования-вставки. В любом случае, использование IDE определенно поможет вам проверить ваш код и обнаружить ошибки раньше. Попробуйте!
Поскольку я не могу запустить ваш код, я не могу точно сказать, почему он не работает, но я могу дать вам несколько советов.
Одна вещь, которая вызывает много вопросов, это следующая строка:
dst_dir = root.replace(source, dest)
Помимо неверного отступа, переменная dst_dir
нигде не используется. Так какой смысл в этом утверждении? Также обратите внимание, что это заменяет все вхождения source
в root
. Для тривиальных случаев это не будет проблемой, но это не очень надежно при любых обстоятельствах. Поэтому по возможности используйте операции с путями из стандартной библиотеки и старайтесь не выполнять ручные строковые операции с путями. В Python 3.4 был введен модуль Pathlib
. Я рекомендую использовать это.
Использование os.walk()
может быть довольно удобным в некоторых случаях, но может быть не лучшим решением для вашего варианта использования. Возможно, рекурсивное использование os.listdir()
будет намного проще, особенно если каталог назначения будет плоским (то есть фиксированным каталогом без подкаталогов).
Возможная реализация (с использованием pathlib
и os.listdir()
) может быть следующей:
import logging
import os
import pathlib
import shutil
import time
SOURCE_DIR_PATH = pathlib.Path('C:\\Temp')
DESTINATION_DIR_PATH = pathlib.Path('D:\\archive')
CUTOFF_DAYS = 14
CUTOFF_TIME = time.time() - CUTOFF_DAYS * 24 * 3600 # two weeks
def move_file(src_file_path, dst_dir_path):
logging.debug('Moving file %s to directory %s', src_file_path,
dst_dir_path)
return # REMOVE THIS LINE TO ACTUALLY PERFORM FILE OPERATIONS
try:
shutil.move(str(src_file_path), str(dst_dir_path))
except OSError:
logging.info('File already exists in destination directory: %s',
src_file_path)
logging.warning('Deleting file %s', src_file_path)
src_file_path.unlink()
def move_files(src_file_paths, dst_dir_path):
for src_file_path in src_file_paths:
if src_file_path.stat().st_ctime < CUTOFF_TIME:
logging.info('Moving file older than %d days: %s', CUTOFF_DAYS,
src_file_path)
move_file(src_file_path, dst_dir_path)
else:
logging.info('Not moving file less than %d days old: %s',
CUTOFF_DAYS, src_file_path)
def purge_files(src_dir_path, dst_dir_path):
logging.info('Scanning directory %s', src_dir_path)
names = os.listdir(src_dir_path)
paths = [src_dir_path.joinpath(name) for name in names]
file_paths = [path for path in paths if path.is_file()]
dir_paths = [path for path in paths if path.is_dir()]
# Cleanup files
move_files(file_paths, dst_dir_path)
# Cleanup directories, recursively.
for dir_path in dir_paths:
purge_files(dir_path, dst_dir_path)
def main():
logging.basicConfig(format='%(message)s', level=logging.DEBUG)
purge_files(SOURCE_DIR_PATH, DESTINATION_DIR_PATH)
if __name__ == '__main__':
main()
Я тестировал этот код, и он работал.
Обратите внимание, что я использовал ту же обработку ошибок для move_file
, что и в вашем примере. Тем не менее, я не думаю, что это достаточно надежно. Что, если в исходном каталоге есть два файла с одинаковым именем (в разных подкаталогах или в разное время)? Затем второй файл будет удален без резервного копирования. Кроме того, в случае других ошибок (таких как «переполнение диска» или «ошибка сети») код просто предполагает, что файл уже был заархивирован, а оригинал удален. Я не знаю ваш вариант использования, но я бы серьезно подумал переписать эту функцию.
Однако я надеюсь, что эти предложения и пример кода приведут вас на правильный путь.