Эквивалентен ли Path.replace os.replace или shutil.move?

#python #file-rename #pathlib

#python #файл-переименовать #pathlib

Вопрос:

В документации к pathlib.Path.replace методу указано:

Переименуйте этот файл или каталог в заданный целевой. Если target указывает на существующий файл или каталог, он будет безоговорочно заменен.

Здесь немного не хватает деталей. Для сравнения, вот документация os.replace :

Переименуйте файл или каталог src в dst . Если dst это каталог, OSError будет поднят. Если dst существует и является файлом, он будет заменен автоматически, если у пользователя есть разрешение. Операция может завершиться неудачей, если src и dst находятся в разных файловых системах. В случае успеха переименование будет атомарной операцией (это требование POSIX).

Важной частью является то, что «Операция может завершиться неудачей, если src и dst находятся в разных файловых системах». В отличие от os.replace , shutil.move этой проблемы нет:

Если пункт назначения находится в текущей файловой системе, то используется os.rename() . В противном случае, src копируется в dst using copy_function , а затем удаляется.

Итак, какая из этих функций Path.replace используется? Есть ли риск Path.replace сбоя из-за того, что адресат находится в другой файловой системе?

Ответ №1:

Path(x).replace(y) просто вызывает os.replace(x, y) . Вы можете видеть это в исходном коде:

 class _NormalAccessor(_Accessor):
    # [...]
    replace = os.replace
    # [...]

_normal_accessor = _NormalAccessor()

# [...]

class Path(PurePath):
    # [...]
    def _init(self,
              # Private non-constructor arguments
              template=None,
              ):
        self._closed = False
        if template is not None:
            self._accessor = template._accessor
        else:
            self._accessor = _normal_accessor

    # [...]

    def replace(self, target):
        """
        Rename this path to the given path, clobbering the existing
        destination if it exists.
        """
        if self._closed:
            self._raise_closed()
        self._accessor.replace(self, target)