Python distutils copy_tree не может обновиться, если есть символические ссылки - PullRequest
0 голосов
/ 31 октября 2018

Я пытаюсь использовать Python distutils.dir_util.copy_tree для копирования содержимого одного каталога в другой и обновления файлов в месте назначения, если они изменились. Я использую варианты:

copy_tree(src, dst, preserve_symlinks=1, update=1)

Это работает для начальной копии, но не на всех последующих с:

FileExistsError: [Errno 17] File exists: 'file1' -> 'test2/file2'

Где file1 - символическая ссылка на file2.

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

Есть ли способ сделать это с помощью этого инструмента? Есть ли лучший инструмент для использования, или мне нужно будет создать свой собственный?

Сведения о платформе:

CentOS Linux 7.5 Анаконда Питон 3.6.6

1 Ответ

0 голосов
/ 08 ноября 2018

Вот моя попытка: прокладка для distutils.dir_util.copy_tree с мартышкой os.symlink.

import contextlib
import os
import distutils.dir_util


@contextlib.contextmanager
def monkeypatch(object, name, patch):
    value_orig = getattr(object, name)
    setattr(object, name, patch)
    yield object
    setattr(object, name, value_orig)


def copy_tree(src, dst, **kwargs):
    stdlib_symlink = os.symlink

    def _symlink(src, dst, **kwargs):
        try:
            stdlib_symlink(src, dst, **kwargs)
        except FileExistsError as err:
            pass

    with monkeypatch(distutils.dir_util.os, 'symlink', _symlink):
        distutils.dir_util.copy_tree(src, dst, **kwargs)

Эта версия функции _symlink будет игнорировать любые ошибки, возникающие при попытках символической ссылки. Вы можете написать свой собственный, который будет воссоздавать символическую ссылку, что-то вроде

def _symlink(src, dst, **kwargs):
    try:
        stdlib_symlink(src, dst, **kwargs)
    except FileExistsError as err:
        os.remove(dst)
        stdlib_symlink(src, dst)
...