Обратный вызов Ignore для python Shutil.copytree() не принимает полный путь

Я хотел бы указать полные пути к игнорируемым файлам и каталогам при вызове Shutil.copytree(). Что-то типа

def my_ignore(dir, files):

    # return ["exclude.file"] # working

    return ["/full_path_to/exclude.file"] # Not working

shutil.copytree(src, dest, ignore=my_ignore)

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

Я упомянул здесь ряд вопросов, таких как: Как написать функцию обратного вызова для игнорирования в Shutil.copytree

Каталог фильтра при использовании Shutil.copytree?

Но ни один из ответов не работает. Похоже, что ловушка игнорирования может возвращать только глобальный стиль, и любой сконструированный полный путь не будет работать.

Я что-то упускаю?


person kakyo    schedule 09.07.2013    source источник


Ответы (2)


ignore действительно должен возвращать только те имена файлов, которые игнорируются. Однако функция вызывается при каждом посещении каталога shutil.copytree(); вы можете игнорировать файлы на каталог.

Если у вас есть полный путь к файлу, который нужно игнорировать, то сопоставьте его с первым параметром, переданным вашей функции ignore; это полный путь к этому каталогу:

def my_ignore(dir, files):
    if dir == '/full_path_to':
        return {"exclude.file"}

Я возвращаю набор здесь; тестирование членства в наборе выполняется быстрее, чем со списком.

Если у вас есть предопределенный набор путей для игнорирования, проанализируйте их в словаре; keys — это путь к каталогу, значения — наборы имен файлов в этом пути:

from collections import defaultdict

to_ignore = defaultdict(set)
for path in ignored_paths:
    dirname, filename = os.path.split(path)
    to_ignore[dirname].add(filename)

def my_ignore(src, files):
    return to_ignore.get(src, set())
person Martijn Pieters    schedule 09.07.2013
comment
Проверка принадлежности в наборе не быстрее, чем в списке, когда есть только один элемент. :-) - person kindall; 09.07.2013
comment
@kindall: я сомневаюсь, что это ограничено только одним именем файла за раз. - person Martijn Pieters; 09.07.2013
comment
@MartijnPieters Является ли ignored_paths списком путей? Я попробовал ваш код и получил ошибку: Файл /HelloCopytree.py, строка 28, в my_ignore2 return to_ignore.get(folder, set()) TypeError: get() не принимает аргументы ключевого слова - person kakyo; 09.07.2013
comment
Мое плохое: я поставил default=set() в качестве аргумента ключевого слова. Ваш код работает нормально. Спасибо! - person kakyo; 09.07.2013

Это не магия. copytree() копирует содержимое одного каталога за раз и специально ищет имена файлов в возвращаемом вами списке игнорирования. Полный путь никогда не является именем файла, поэтому он никогда не совпадает.

Однако параметр dir поможет вам сделать то, что вы хотите:

def my_ignore(dir, files):
    if dir == "/full/path/to":
        return ["exclude.file"]
    else:
        return []
person kindall    schedule 09.07.2013