Подтвердить что ты не робот

Скопировать файл с помощью pathlib в Python

Я пытаюсь скопировать файл с pathlib

import pathlib
import shutil

my_file=pathlib.Path('/etc/hosts')
to_file=pathlib.Path('/tmp/foo')
shutil.copy(my_file, to_file)

Я получаю это исключение:

/home/foo_egs_d/bin/python /home/foo_egs_d/src/test-pathlib-copy.py
Traceback (most recent call last):
  File "/home/foo_egs_d/src/test-pathlib-copy.py", line 6, in <module>
    shutil.copy(my_file, to_file)
  File "/usr/lib/python2.7/shutil.py", line 117, in copy
    if os.path.isdir(dst):
  File "/home/foo_egs_d/lib/python2.7/genericpath.py", line 41, in isdir
    st = os.stat(s)
TypeError: coercing to Unicode: need string or buffer, PosixPath found

Process finished with exit code

... как скопировать файл с помощью pathlib в Python 2.7?

4b9b3361

Ответ 1

Так что по этому поводу?

import pathlib
import shutil

my_file = pathlib.Path('/etc/hosts')
to_file = pathlib.Path('/tmp/foo')
shutil.copy(str(my_file), str(to_file))

Проблема в том, что pathlib.Path создайте объект PosixPath, если вы используете Unix/Linux, WindowsPath, если вы используете Microsoft Windows.

Но shutil.copy() принимает строку в качестве аргумента. Так что просто используйте функцию str() здесь, когда вы используете функцию str() для объекта Path, он вернет путь, который объект Path называет строкой.

Ответ 2

Причина для shutil.copy() не работает в том, что вы не используете последние Python, Python 3.6 shutil.copy() можете обрабатывать объекты Path (или их подклассы). Для более старых версий Python это вызывает ошибку, потому что в тех реализациях shutil ожидаются строковые аргументы для аргументов типа copy, а не pathlib.Path.

На самом деле вы хотите написать:

my_file.copy(to_file)

Вы можете подклассифицировать Path для включения такого метода и адаптировать создание my_file. Мне легче просто трансформировать/обезьяна-патч/утка-пробить его на существующий pathlib.Path

from pathlib import Path


def _copy(self, target):
    import shutil
    assert self.is_file()
    shutil.copy(str(self), str(target))  # str() only there for Python < (3, 6)

Path.copy = _copy

Вы можете поместить этот код в любом месте, пока он выполняется, до вызова метода .copy в любом из экземпляров Path. Аргумент .copy() может быть файлом или каталогом.

Ответ 3

Начиная с Python 3.5, без импорта shutil, вы можете сделать:

from pathlib import Path

dest = Path('dest')
src = Path('src')
dest.write_bytes(src.read_bytes()) #for binary files
dest.write_text(src.read_text()) #for text files

Для Python 2.7 pathlib2 предоставляет read_bytes, read_text, write_bytes и write_text.

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

Согласно комментариям, можно использовать write_bytes и read_bytes для копирования текстовых файлов, но если вам нужно иметь дело с кодировкой во время копирования write_text, read_text предоставляет преимущество двух дополнительных параметров:

  • encoding - это имя кодировки, используемой для декодирования или кодирования файла.
  • errors - это необязательная строка, которая определяет, как должны обрабатываться ошибки кодирования и декодирования.

Они оба имеют то же значение, что и в open().

Ответ 4

Как shutil был преобразован для принятия pathlib.Path объектов в Python 3.6

Как упоминалось в fooobar.com/questions/417004/..., shutil в Python 3.6 может принимать pathlib.Path объекты.

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

Улучшение было результатом PEP 519: https://www.python.org/dev/peps/pep-0519/

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

Там, где это задокументировано, stlib ссылается на глоссарий для "похожих на путь объектов": https://docs.python.org/3/glossary.html#term-path-like-object

Объект, представляющий путь к файловой системе. Объект, подобный пути, - это либо объект str или bytes, представляющий путь, либо объект, реализующий протокол os.PathLike. Объект, который поддерживает протокол os.PathLike, может быть преобразован в путь файловой системы str или bytes путем вызова функции os.fspath(); os.fsdecode() и os.fsencode() могут использоваться для гарантии результата str или bytes, соответственно. Представлено PEP 519.

а затем ссылки на документацию os.PathLike: https://docs.python.org/3/glossary.html#term-path-like-object

Абстрактный базовый класс для объектов, представляющих путь к файловой системе, например, pathlib.PurePath.

Новое в версии 3.6.

abstractmethod __fspath__()

Возвращает представление пути к файловой системе объекта.

Метод должен возвращать только объект str или bytes, причем предпочтение отдается str.

Ключевые коммиты реализации выглядят так:

Если вы хотите реализовать свои собственные классы, подобные путям, вы можете сделать это следующим образом:

#!/usr/bin/env python3

class MyPath:
    def __init__(self, path):
        self.path = path
    def __fspath__(self):
        return self.path

with open(MyPath('f'), 'w'):
    pass

Протестировано в Python 3.6.7, Ubuntu 18.10.

Ответ 5

Вы можете использовать метод переименования pathlib вместо shutil.move().

import pathlib

my_file = pathlib.Path('/etc/hosts')
to_file = pathlib.Path('/tmp/foo')
my_file.rename(to_file)