105

I try to copy a file with pathlib

import pathlib
import shutil

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

I get this exception:

/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

... how to copy file with pathlib in Python 2.7?

4

6 回答 6

115

要使用shutil.copy

import pathlib
import shutil

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

shutil.copy(str(my_file), str(to_file))  # For Python <= 3.7.
shutil.copy(my_file, to_file)  # For Python 3.8+.

如果您使用的是 Unix/Linux,问题是pathlib.Path创建一个对象,如果您使用的是 Microsoft Windows。PosixPathWindowsPath

对于旧版本的 Python,shutil.copy需要一个字符串作为其参数。对于他们,请使用str此处的功能。

于 2015-11-10T09:01:52.700 回答
44

不工作的原因shutil.copy()是你没有使用最新的 Python,Python 3.6shutil.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实例的方法之前执行即可。to 的参数.copy()可以是文件或目录。

于 2016-10-29T12:25:01.007 回答
37

从 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,提供pathlib2read_bytesread_text方法。write_byteswrite_text

该文件将被加载到内存中,因此此方法不适用于大于机器可用内存的文件。

根据评论,可以使用write_bytesandread_bytes复制文本文件,但如果您需要在复制时处理编码,则可以使用两个write_text额外read_text参数的优势:

  • encoding是用于解码或编码文件的编码名称
  • errors是一个可选字符串,指定如何处理编码和解码错误

它们都具有与 中相同的含义open()

于 2017-10-26T14:34:47.217 回答
23

如何在 Python 3.6shutil中转换为接受对象pathlib.Path

this answer中所述,Python 3.6 中的 shutil 可以获取pathlib.Path对象。

因为这感觉很神奇,所以我决定研究一下它是如何实现的,看看我是否能够在我自己的课程中重用这个魔法。

改进是PEP 519的结果。

这概括了许多 stdlib 功能,因此文档没有得到一致的更新,包括shutil从 3.7开始的大多数文档仅支持单个函数。欢迎来到动态打字的乐趣。

在记录的情况下,stlib 链接到“类路径对象”的词汇表

表示文件系统路径的对象。类路径对象是表示路径的 str 或字节对象,或者是实现 os.PathLike 协议的对象。支持 os.PathLike 协议的对象可以通过调用 os.fspath() 函数转换为 str 或 bytes 文件系统路径;os.fsdecode() 和 os.fsencode() 可分别用于保证 str 或 bytes 结果。由 PEP 519 引入。

然后链接到以下文档os.PathLike

代表文件系统路径的对象的抽象基类,例如 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 中测试。

于 2019-04-21T09:28:28.530 回答
4

您可能会使用 pathlib3x - 它提供了最新的(在撰写此答案 Python 3.10.a0 之日)Python 3.6 或更高版本的 Python pathlib 的反向端口,以及一些附加功能,如copy,copy2等...

$> python -m pip install pathlib3x
$> python
>>> import pathlib3x as pathlib
>>> my_file = pathlib.Path('/etc/hosts')
>>> to_file = pathlib.Path('/tmp/foo')
>>> my_file.copy(to_file)

你可以在githubPyPi上找到它


免责声明:我是 pathlib3x 库的作者。

于 2020-07-05T13:44:18.770 回答
4

您可以使用pathlib重命名方法而不是shutil.move().

import pathlib

my_file = pathlib.Path('/etc/hosts')
to_file = pathlib.Path('/tmp/foo')
my_file.rename(to_file)
于 2017-07-12T22:44:45.540 回答