文章目录
- pathlib -- 面向对像的文件系统路径
- 1、python常规路径处理中的问题
- 2、填加并创建新的路径
- 3、创建文件夹和文件重命名
- 4、列举文件夹下特定文件类型
- 5、打开多个文件并读取内容
- 5、pathlib模块分析
- 5.1 运算符
- 5.2 属性和方法
- 5.2.1 Path.parts
- 5.2.2 Path.parents & Path.parent
- 5.2.3 Path.name
- 5.2.3 Path.suffixes & Path.suffix
- 5.2.4 Path.stem
- 5.2.5 Path.joinpath
- 5.2.6 Path.cwd()
- 5.2.7 Path.home()
- 5.2.8 Path.exists()
- 5.2.9 Path.expanduser()
- 5.2.10 Path.glob()
- 5.2.11 Path.rglob()
- 5.2.12 Path.is_dir()
- 5.2.13 Path.is_file()
- 5.2.14 Path.is_absolute()
- 5.2.15 Path.iterdir()
- 5.2.16 Path.mkdir(mode=0o777, parents=False, exist_ok=False)
- 5.2.17 Path.open(mode=’r’, buffering=-1, encoding=None, errors=None, newline=None)
- 5.2.18 Path.rename(target)
- 5.2.18 Path.replace(target)
- 5.2.19 Path.resolve(strict=False)
- 5.2.20 Path.rmdir
- 参考资料
pathlib – 面向对像的文件系统路径
从python3.4以后,pathlib内置,最初只是以为pathlib
只是os.path
功能的一个面像对像话,但在2019年,Django框架将os.path
用pathlib换了。以下将简单说明。
1、python常规路径处理中的问题
在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来实现这个功能
2、填加并创建新的路径
当你想要实现以下功能:
- 当前路径下有一个
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
3、创建文件夹和文件重命名
有两个演示:
- 在src/stuff己经创建的情况下,尝试创建
- 将src下文件.config重命名成.stuffconfig
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")
4、列举文件夹下特定文件类型
递归列举文件下所有指定类型的文件,比如所有.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')]
5、打开多个文件并读取内容
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']
5、pathlib模块分析
pathlib中有几个不同的类,主要是针对不同的操作系统,这里主要讲Path这个类
5.1 运算符
在产生子目录时,可以使用/
来代替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
5.2 属性和方法
下表,列出了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
5.2.1 Path.parts
会将整个路径的各个部分,以元组的形式的返回
from pathlib import Path
file_path = Path("src/stuff/__init__.py")
print(file_path.parts)
('src', 'stuff', '__init__.py')
5.2.2 Path.parents & Path.parent
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')
5.2.3 Path.name
返回路径的最后一部分,适合获得最后名字
file_path = Path("src/module.py")
file_path.name
'module.py'
5.2.3 Path.suffixes & Path.suffix
Path.suffixes
将会返回所有的后缀,Path.suffix
只返回最后的一个后缀
file_path = Path("src/somefile.tar.gz")
print(file_path.suffixes)
print(file_path.suffix)
['.tar', '.gz']
.gz
5.2.4 Path.stem
将返回文件名中除后缀以外的部分
file_path = Path("src/somefile.tar.gz")
print(file_path.stem)
somefile.tar
5.2.5 Path.joinpath
可以将多个路径拼接起来,代替使用/
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
5.2.6 Path.cwd()
类似os.getcwd(),返回当前路径
print(Path.cwd())
print(os.getcwd())
/home/tl/test
/home/tl/test
5.2.7 Path.home()
返回home路径
print(Path.home())
/home/tl
5.2.8 Path.exists()
判断文件或文件夹是否存在,返回boolean数据
print(Path("src/stuff/thisisabsent.py").exists())
print(Path("src/stuff/__init__.py").exists())
False
True
5.2.9 Path.expanduser()
将~
置换成返回带有路径的新路径
print(Path("~/test/usr/stuff/__init__.py").expanduser())
/home/tl/test/usr/stuff/__init__.py
5.2.10 Path.glob()
返回所有符合正则表达的内容,返回的是生成器
#获取所有src/stuff文件夹下,以.py为后缀的文件
for fname in Path("src/stuff").glob("*.py"):
print(fname)
src/stuff/__init__.py
src/stuff/submodule.py
5.2.11 Path.rglob()
以递归的方式,返回所有符合要求的文件路径
# 比如要返回所有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
5.2.12 Path.is_dir()
返回路径是否为路径,返回类型为 boolean
print(Path("src/stuff").is_dir())
print(Path("src/stuff/__init__.py").is_dir())
True
False
5.2.13 Path.is_file()
返回路径是否为文件,返回类型为 boolean
print(Path("src/stuff").is_file())
print(Path("src/stuff/__init__.py").is_file())
False
True
5.2.14 Path.is_absolute()
返回路径是否为绝对路径,如果是相以路径,则返返False
print(Path("src/stuff/__init__.py").is_absolute())
print(Path("/home/tl/test/src/stuff/__init__.py").is_absolute())
False
True
5.2.15 Path.iterdir()
如果路径点指向文件夹,将返回当前文件夹下的所有文件和文件夹的路径
for content in Path('src').iterdir():
print(content)
src/.stuffconfig
src/somefile.tar.gz
src/module.py
src/b.py
src/stuff
5.2.16 Path.mkdir(mode=0o777, parents=False, exist_ok=False)
在给定路径下创建新路径。
- mode:文件的权限控制
- parentes:如是是True,那么缺失的路径中的内容都会自动创建,否则会报FileNotFoundError的错
- exist_ok:如果是False,那么当路径已经存在时,会报错;当是True时,会忽略报错
Path("src/other/side").mkdir(parents=True)
5.2.17 Path.open(mode=’r’, buffering=-1, encoding=None, errors=None, newline=None)
和内建函数open一样
with Path("src/module.py").open('r') as f:
content = f.read()
print(content)
this is module.py
5.2.18 Path.rename(target)
对文件或文件夹重名命,并指向新的文件。如果要重命名的文件不存在,那么就会报错。
Path("src/stuff/submodule.py").rename("src/stuff/anothermodule.py")
5.2.18 Path.replace(target)
和rename有些相似,以target代替原文件
file_path = Path("src/stuff/anothermodule.py")
file_path.replace(file_path.parent / "Dockerfile")
5.2.19 Path.resolve(strict=False)
返回绝对路径,如果strick是True,并且文件不存在则会报错
Path("src/stuff/Dockerfile").resolve()
PosixPath('/home/tl/test/src/stuff/Dockerfile')
5.2.20 Path.rmdir
删除路径,一定要保证文件夹是空的,否则报错,相当于os.rmdir
参考资料
https://docs.python.org/3/library/pathlib.html