从python3.4以后,pathlib内置,最初只是以为pathlib
只是os.path
功能的一个面像对像话,但在2019年,Django框架将os.path
用pathlib换了。以下将简单说明。
在python常规的路径处理中,仅把路径当做字符串路径,到目前为止,尽管有点麻烦,但使用路径作为os.path模块的字符串已经足够了。但是,路径实际上并不是字符串,因此必须使用多个模块来提供分散在整个标准库中的不同功能,包括os,glob和shutil等库。以下代码仅使用三个模块将多个python文件从当前目录复制到另一个名为src的目录。
import os
import shutil
import glob
fnames = glob.glob("*.py")
for fname in fnames:
new_path = os.path.join("src",fname)
shutil.copy(fname,new_path)
以上操作比较复杂,用到多个模块,下面将逐步介绍pathlib来实现这个功能
当你想要实现以下功能:
file.txt
,相要创建一个file_another.txt
的文件file_another.txt
的绝对路径保存到一个变量中看一下如何使用os
来实现
from os.path import abspath,join,dirname
file_path=abspath("file.txt")
base_dir = dirname(file_path)
file_another_path = join(base_dir,"file_another.txt")
print(file_path)
print(base_dir)
print(file_another_path)
/home/tl/test/file.txt
/home/tl/test
/home/tl/test/file_another.txt
相同的功能用pathlib来实现
from pathlib import Path
file_path = Path('file.txt').resolve()
base_dir = file_path.parent
file_another_path=base_dir / "file_another.txt"
print(file_path)
print(base_dir)
print(file_another_path)
/home/tl/test/file.txt
/home/tl/test
/home/tl/test/file_another.txt
有两个演示:
os.makedirs(os.path.join("src","stuff"),exist_ok=True)
os.rename("src/.config","src/.stuffconfig")
使用pathlib来做相同的事
from pathlib import Path
Path("src/stuff").mkdir(parents=True,exist_ok=True)
Path("src/.config").rename("src/.stuffconfig")
递归列举文件下所有指定类型的文件,比如所有.py文件
src/
├── stuff
│ ├── __init__.py
│ └── submodule.py
├── .stuffconfig
├── b.py
└── module.py
#通常是使用glob第三方包来解决这个问题
import glob
top_level_py_files = glob.glob("src/*.py")
all_py_files = glob.glob("src/**/*.py",recursive=True)
print(top_level_py_files)
print(all_py_files)
['src/module.py', 'src/b.py']
['src/module.py', 'src/b.py', 'src/stuff/__init__.py', 'src/stuff/submodule.py']
以上方法可以很好的解决问题,但需要调用第三方包,如果只是用一个包, 那么pathlib包含glob
和rglob
功能,可以实现相同功能
from pathlib import Path
top_level_py_files =Path("src").glob("*.py")
all_py_files = Path("src").rglob("*.py")
print(list(top_level_py_files))#返回的是生成器,所以要加list
print(list(all_py_files))
[PosixPath('src/module.py'), PosixPath('src/b.py')]
[PosixPath('src/module.py'), PosixPath('src/b.py'), PosixPath('src/stuff/__init__.py'), PosixPath('src/stuff/submodule.py')]
import glob
contents=[]
for fname in glob.glob("src/**/*.py",recursive=True):
with open(fname,'r') as f:
contents.append(f.read())
print(contents)
['this is module.py', 'this is b.py\n', 'this is stuff/__init__.py', 'this is stuff/submodule.py']
pathlib可以实现几乎一样的功能
from pathlib import Path
contents=[]
for fname in Path("src").rglob("*.py"):
with open(fname,'r') as f:
contents.append(f.read())
print(contents)
['this is module.py', 'this is b.py\n', 'this is stuff/__init__.py', 'this is stuff/submodule.py']
pathlib中有几个不同的类,主要是针对不同的操作系统,这里主要讲Path这个类
在产生子目录时,可以使用/
来代替os.path.join
from pathlib import Path
base_dir = Path("src")
child_path = base_dir / "stuff"
file_path = child_path / "__init__.py"
print(file_path)
src/stuff/__init__.py
下表,列出了Path
的一些属性和方法
Path
│
├── Attributes
│ ├── parts
│ ├── parent & parents
│ ├── name
│ ├── suffix & suffixes
│ └── stem
│
│
└── Methods
├── joinpath(*other)
├── cwd()
├── home()
├── exists()
├── expanduser()
├── glob()
├── rglob(pattern)
├── is_dir()
├── is_file()
├── is_absolute()
├── iterdir()
├── mkdir(mode=0o777, parents=False, exist_ok=False)
├── open(mode='r', buffering=-1, encoding=None, errors=None, newline=None)
├── rename(target)
├── replace(target)
├── resolve(strict=False)
└── rmdir()
我们将逐一使用以上内容的进行说明,使用的例子如下:
src/
├── stuff
│ ├── __init__.py
│ └── submodule.py
├── .stuffconfig
├── somefile.tar.gz
└── module.py
会将整个路径的各个部分,以元组的形式的返回
from pathlib import Path
file_path = Path("src/stuff/__init__.py")
print(file_path.parts)
('src', 'stuff', '__init__.py')
Path.parents
返回一个不可变的逐次父路径;而Path.parent
则返回当前路径的父路径
file_path = Path("src/stuff/__init__.py")
for parent in file_path.parents:
print(parent)
src/stuff
src
.
file_path.parent
PosixPath('src/stuff')
返回路径的最后一部分,适合获得最后名字
file_path = Path("src/module.py")
file_path.name
'module.py'
Path.suffixes
将会返回所有的后缀,Path.suffix
只返回最后的一个后缀
file_path = Path("src/somefile.tar.gz")
print(file_path.suffixes)
print(file_path.suffix)
['.tar', '.gz']
.gz
将返回文件名中除后缀以外的部分
file_path = Path("src/somefile.tar.gz")
print(file_path.stem)
somefile.tar
可以将多个路径拼接起来,代替使用/
file_path = Path("src").joinpath("stuff").joinpath("__init__.py")
print(file_path)
file_path = Path("src") / "stuff" / "__init__.py"
print(file_path)
src/stuff/__init__.py
src/stuff/__init__.py
类似os.getcwd(),返回当前路径
print(Path.cwd())
print(os.getcwd())
/home/tl/test
/home/tl/test
返回home路径
print(Path.home())
/home/tl
判断文件或文件夹是否存在,返回boolean数据
print(Path("src/stuff/thisisabsent.py").exists())
print(Path("src/stuff/__init__.py").exists())
False
True
将~
置换成返回带有路径的新路径
print(Path("~/test/usr/stuff/__init__.py").expanduser())
/home/tl/test/usr/stuff/__init__.py
返回所有符合正则表达的内容,返回的是生成器
#获取所有src/stuff文件夹下,以.py为后缀的文件
for fname in Path("src/stuff").glob("*.py"):
print(fname)
src/stuff/__init__.py
src/stuff/submodule.py
以递归的方式,返回所有符合要求的文件路径
# 比如要返回所有src文件夹下以.py为后缀的文件
for fname in Path("src").rglob("*.py"):
print(fname)
src/module.py
src/b.py
src/stuff/__init__.py
src/stuff/submodule.py
返回路径是否为路径,返回类型为 boolean
print(Path("src/stuff").is_dir())
print(Path("src/stuff/__init__.py").is_dir())
True
False
返回路径是否为文件,返回类型为 boolean
print(Path("src/stuff").is_file())
print(Path("src/stuff/__init__.py").is_file())
False
True
返回路径是否为绝对路径,如果是相以路径,则返返False
print(Path("src/stuff/__init__.py").is_absolute())
print(Path("/home/tl/test/src/stuff/__init__.py").is_absolute())
False
True
如果路径点指向文件夹,将返回当前文件夹下的所有文件和文件夹的路径
for content in Path('src').iterdir():
print(content)
src/.stuffconfig
src/somefile.tar.gz
src/module.py
src/b.py
src/stuff
在给定路径下创建新路径。
Path("src/other/side").mkdir(parents=True)
和内建函数open一样
with Path("src/module.py").open('r') as f:
content = f.read()
print(content)
this is module.py
对文件或文件夹重名命,并指向新的文件。如果要重命名的文件不存在,那么就会报错。
Path("src/stuff/submodule.py").rename("src/stuff/anothermodule.py")
和rename有些相似,以target代替原文件
file_path = Path("src/stuff/anothermodule.py")
file_path.replace(file_path.parent / "Dockerfile")
返回绝对路径,如果strick是True,并且文件不存在则会报错
Path("src/stuff/Dockerfile").resolve()
PosixPath('/home/tl/test/src/stuff/Dockerfile')
删除路径,一定要保证文件夹是空的,否则报错,相当于os.rmdir
https://docs.python.org/3/library/pathlib.html