【问题标题】:Python distutils copy_tree fails to update if there are symlinks如果有符号链接,Python distutils copy_tree 无法更新
【发布时间】:2018-11-08 05:27:23
【问题描述】:

我正在尝试使用 Python distutils.dir_util.copy_tree 将一个目录的内容复制到另一个目录,并在目标文件发生更改时更新它们。我正在使用选项:

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

这适用于初始副本,但在所有后续副本上都失败:

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

其中file1file2 的符号链接。

我不需要它来更新符号链接。如果它只是第二次忽略它们,或者盲目地覆盖它们,那很好。但是,实际上,在更新模式下复制包含符号链接的目录似乎是不可能的。

有没有办法使用这个工具来做到这一点?有没有更好的工具可以使用,还是我需要自己创建?

平台详情:

CentOS Linux 7.5 蟒蛇 Python 3.6.6

【问题讨论】:

  • 好问题。我想我会在调用copy_tree 之前使用容易出错的版本(跳过现有的符号链接或删除并重新创建它们)进行monkeypatch os.symlink,然后在copy_tree 完成后将os.symlink 恢复为原始函数。或者只是通过subprocess.Popen 拨打rsync :-)
  • 我实际上是为了替换使用rsync 方法的旧代码而写的。我需要更多地控制事物的同步方式。不过,猴子补丁的想法听起来很有希望。

标签: python distutils


【解决方案1】:

这是我的尝试: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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-09
    • 1970-01-01
    • 1970-01-01
    • 2017-01-10
    相关资源
    最近更新 更多