在 Python 中使用 pathlib 复制文件
Copy file with pathlib in 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
...如何在 Python 2.7 中使用 pathlib 复制文件?
使用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+.
问题是 pathlib.Path
如果您使用 Unix/Linux 创建一个 PosixPath
对象,如果您使用 Microsoft Windows WindowsPath
。
对于旧版本的 Python,shutil.copy
需要一个字符串作为其参数。对于他们,请在此处使用 str
功能。
shutil.copy()
不工作的原因是你没有使用最新的Python,Python3.6shutil.copy()
can 处理 Path
个对象(或其子类)。对于旧版本的 Python 这会引发错误,因为 shutil
的那些实现需要 copy
的字符串参数,而不是 pathlib.Path
类型的参数。
你真正想写的是:
my_file.copy(to_file)
您可以将 Path 子类化以包含这样的方法,并适应 my_file
的创建。我发现在现有 pathlib.Path
上 graft/monkey-patch/duck-punch 它更容易
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
您可以将此代码放在任何您喜欢的地方,只要它在对任何 Path
实例调用 .copy
方法之前执行即可。 .copy()
的参数可以是文件或目录。
您可以使用 pathlib
重命名方法代替 shutil.move()
。
import pathlib
my_file = pathlib.Path('/etc/hosts')
to_file = pathlib.Path('/tmp/foo')
my_file.rename(to_file)
从 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()
相同。
如何在 Python 3.6
中将 shutil
转换为接受 pathlib.Path
个对象
如 所述,Python 3.6 中的 shutil 可以接收 pathlib.Path
个对象。
因为这感觉很神奇,所以我决定稍微调查一下它是如何实现的,看看我是否能够自己重用这个魔法 类。
改进是 PEP 519 的结果。
这概括了许多 stdlib 功能,因此文档没有持续更新,包括从 3.7 only documents support in a single function 开始的大部分 shutil
。欢迎体验动态类型的乐趣。
在记录的地方,stlib 链接到 glossary for "path-like objects"。
An object representing a file system path. A path-like object is either a str or bytes object representing a path, or an object implementing the os.PathLike protocol. An object that supports the os.PathLike protocol can be converted to a str or bytes file system path by calling the os.fspath() function; os.fsdecode() and os.fsencode() can be used to guarantee a str or bytes result instead, respectively. Introduced by PEP 519.
然后链接到 os.PathLike
的文档:
An abstract base class for objects representing a file system path, e.g. pathlib.PurePath.
New in version 3.6.
abstractmethod __fspath__()
Return the file system path representation of the object.
The method should only return a str or bytes object, with the preference being for str.
关键实现提交似乎是:
- 3f9183b5aca568867f37c38501fca63911580c66 这基本上改变了在
Modules/posixmodule.c
处的最低级别路径操作点
- 568be63248614a2cdd7666a67ddfd16e817f7db9 将
__fspath__
添加到 pathlib.PurePath
如果你想实现你自己的类路径类,你可以这样做:
#!/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 中测试。
您可以使用 pathlib3x - 它提供了最新的向后移植(在撰写此答案的日期 Python 3.11.a0)Python Python 3.6 或更新版本的 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)
上找到它
免责声明:我是 pathlib3x 库的作者。
我尝试使用 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
...如何在 Python 2.7 中使用 pathlib 复制文件?
使用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+.
问题是 pathlib.Path
如果您使用 Unix/Linux 创建一个 PosixPath
对象,如果您使用 Microsoft Windows WindowsPath
。
对于旧版本的 Python,shutil.copy
需要一个字符串作为其参数。对于他们,请在此处使用 str
功能。
shutil.copy()
不工作的原因是你没有使用最新的Python,Python3.6shutil.copy()
can 处理 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
您可以将此代码放在任何您喜欢的地方,只要它在对任何 Path
实例调用 .copy
方法之前执行即可。 .copy()
的参数可以是文件或目录。
您可以使用 pathlib
重命名方法代替 shutil.move()
。
import pathlib
my_file = pathlib.Path('/etc/hosts')
to_file = pathlib.Path('/tmp/foo')
my_file.rename(to_file)
从 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()
相同。
如何在 Python 3.6
中将shutil
转换为接受 pathlib.Path
个对象
如 pathlib.Path
个对象。
因为这感觉很神奇,所以我决定稍微调查一下它是如何实现的,看看我是否能够自己重用这个魔法 类。
改进是 PEP 519 的结果。
这概括了许多 stdlib 功能,因此文档没有持续更新,包括从 3.7 only documents support in a single function 开始的大部分 shutil
。欢迎体验动态类型的乐趣。
在记录的地方,stlib 链接到 glossary for "path-like objects"。
An object representing a file system path. A path-like object is either a str or bytes object representing a path, or an object implementing the os.PathLike protocol. An object that supports the os.PathLike protocol can be converted to a str or bytes file system path by calling the os.fspath() function; os.fsdecode() and os.fsencode() can be used to guarantee a str or bytes result instead, respectively. Introduced by PEP 519.
然后链接到 os.PathLike
的文档:
An abstract base class for objects representing a file system path, e.g. pathlib.PurePath.
New in version 3.6.
abstractmethod __fspath__()
Return the file system path representation of the object.
The method should only return a str or bytes object, with the preference being for str.
关键实现提交似乎是:
- 3f9183b5aca568867f37c38501fca63911580c66 这基本上改变了在
Modules/posixmodule.c
处的最低级别路径操作点
- 568be63248614a2cdd7666a67ddfd16e817f7db9 将
__fspath__
添加到pathlib.PurePath
如果你想实现你自己的类路径类,你可以这样做:
#!/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 中测试。
您可以使用 pathlib3x - 它提供了最新的向后移植(在撰写此答案的日期 Python 3.11.a0)Python Python 3.6 或更新版本的 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)
上找到它
免责声明:我是 pathlib3x 库的作者。