本文介绍IO、pathlib、shutil三个模块对文件进行创建/读写/移动/删除等的方法
1.IO操作文件
1.1 文件打开命令一览表
f = open("1.txt", "w")
第一个参数指定的是文件路径和文件名,这里我们没有添加路径的话,那么默认是将文件创建在 Python 的主文件夹下面,因为执行 IDLE 的程序就放在那里嘛(同样的道理,如果我们在桌面创建一个 test.py 的源文件,然后输入打开文件的代码,那么它就会在桌面创建一个 FishC.txt 的文本文件)。
第二个参数是指定文件的打开模式:
字符串 | 含义 |
---|---|
‘r’ | 读取(默认) |
‘w’ | 写入(如果文件已存在则先截断清空文件) |
‘x’ | 排他性创建文件(如果文件已存在则打开失败) |
‘a’ | 追加(如果文件已存在则在末尾追加内容) |
‘b’ | 二进制模式 |
‘t’ | 文本模式(默认) |
‘+’ | 更新文件(读取和写入) |
1.2 文件操作命令一览表
方法 | 含义 |
---|---|
f.close() | 关闭文件对象 |
f.flush() | 将文件对象中的缓存数据写入到文件中(不一定有效) |
f.read(size=-1, /) | 从文件对象中读取指定数量的字符(或者遇到 EOF 停止);当未指定该参数,或该参数为负值的时候,读取剩余的所有字符 |
f.readable() | 判断该文件对象是否支持读取(如果返回的值为 False,则调用 read() 方法会导致 OSError 异常) |
f.readline(size=-1, /) | 从文件对象中读取一行字符串(包括换行符),如果指定了 size 参数,则表示读取 size 个字符 |
f.seek(offset, whence=0, /) | 修改文件指针的位置,从 whence 参数指定的位置(0 代表文件起始位置,1 代表当前位置,2 代表文件末尾)偏移 offset 个字节,返回值是新的索引位置 |
f.seekable() | 判断该文件对象是否支持修改文件指针的位置(如果返回的值为 False,则调用 seek(),tell(),truncate()方法都会导致 OSError 异常) |
f.tell() | 返回当前文件指针在文件对象中的位置 |
f.truncate(pos=None, /) | 将文件对象截取到 pos 的位置,默认是截取到文件指针当前指定的位置 |
f.write(text, /) | 将字符串写入到文件对象中,并返回写入的字符数量(字符串的长度) |
f.writable() | 判断该文件对象是否支持写入(如果返回的值为 False,则调用 write() 方法会导致 OSError 异常) |
f.writelines(lines, /) | 将一系列字符串写入到文件对象中(不会自动添加换行符,所以通常是人为地加在每个字符串的末尾) |
1.3 with关键字
上文用法中,对文件读写都必须是open()-close()方法成对出现,否则会出现文件写入未保存(写入内容实际只存放在了Python缓存)的问题。为了简化语句,同时提高安全性、即时保存文件和释放内存,可以选用with关键字,语法如下:
with open('path','读写模式‘) as f:
do something
1.4 Python对象持久化
pickle
pickle 模块支持将 Python 的代码序列化,解决永久存储 Python 对象的问题。
用法:
pickle.dump(对象,路径) 持久化存储对象到文件(文件后缀要求是 .pkl)
**对象=pickle.load(路径) **读取.pkl文件存储的对象
3.pathlib处理文件
3.1 获取目录
- Path.cwd(),返回文件当前所在目录。
- Path.home(),返回用户的主目录。
应用示例:
from pathlib import Path
currentPath = Path.cwd()
homePath = Path.home()
print("文件当前所在目录:%s\n用户主目录:%s" %(currentPath, homePath))
3.2 目录拼接
斜杠 / 操作符用于拼接路径,比如创建子路径。
应用示例:
from pathlib import Path
currentPath = Path.cwd()
newPath = currentPath / 'python-100'
print("新目录为:%s" %(newPath))
相对路径解析
Path.resolve()方法
应用示例:
>>> Path('./doc').resolve()
WindowsPath('C:/Users/goodb/AppData/Local/Programs/Python/Python39/Doc')
>>> Path('../FishC').resolve()
WindowsPath('C:/Users/goodb/AppData/Local/Programs/Python/FishC')
os.path.relpath(path, start):返回从start到path的相对路径,如不提供start则默认从当前工作目录开始
3.3 创建、删除目录
- Path.mkdir(),创建给定路径的目录。
- 如果目录已存在会报错,此时加入参数exist_ok=True可强制创建
- 如果一次性创建多级子目录,子目录不存在会报错,此时加入参数parents=True可强制创建
- Path.rmdir(),删除该目录,目录文件夹必须为空。
应用示例:
from pathlib import Path
currentPath = Path.cwd()
makePath = currentPath / 'python-100'
makePath.mkdir()
print("创建的目录为:%s" %(nmakePath))
from pathlib import Path
currentPath = Path.cwd()
delPath = currentPath / 'python-100'
delPath.rmdir()
print("删除的目录为:%s" %(delPath))
3.4 读写/删除/重命名文件
- Path.open(mode=’r’),以 “r” 格式打开 Path 路径下的文件,若文件不存在即创建后打开。
- Path.touch(exist_ok=False),创建Path 路径下的文件,若文件存在则无操作。
- Path.read_bytes(),打开 Path 路径下的文件,以字节流格式读取文件内容,等同 open 操作文件的 “rb” 格式。
- Path.read_text(),打开 Path 路径下的文件,以 str 格式读取文件内容,等同 open 操作文件的 “r” 格式。
- Path.write_bytes(),对 Path 路径下的文件进行写操作,等同 open 操作文件的 “wb” 格式。
- Path.write_text(),对 Path 路径下的文件进行写操作,等同 open 操作文件的 “w” 格式。
- Path.rename(新路径),将 Path 路径下的文件移动到 新路径 ,如新路径文件名与Path不同,则同时修改文件名
- Path.unlink(),对 Path 路径下的文件进行删除操作
应用示例:
from pathlib import Path
currentPath = Path.cwd()
mkPath = currentPath / 'python-100.txt'
with mkPath.open('w') as f: # 创建并以 "w" 格式打开 python-100.txt 文件。
f.write('python-100') # 写入 python-100 字符串。
f = open(mkPath, 'r')
print("读取的文件内容为:%s" % f.read())
f.close()
from pathlib import Path
currentPath = Path.cwd()
mkPathText = currentPath / 'python-100-text.txt'
mkPathText.write_text('python-100')
print("读取的文件内容为:%s" % mkPathText.read_text())
str2byte = bytes('python-100', encoding = 'utf-8')
mkPathByte = currentPath / 'python-100-byte.txt'
mkPathByte.write_bytes(str2byte)
print("读取的文件内容为:%s" % mkPathByte.read_bytes())
Path.stat()
Path.stat().size()获取文件大小
3.5 获取文件所在目录的不同部分字段
- Path.resolve(),通过传入文件名,返回文件的完整路径。
- Path.name,可以获取文件的名字,包含后缀名。
- Path.parent,返回文件所在文件夹的名字。
- Path.parents,返回文件所在各级目录的路径组成的不可变集合(可迭代)。
- Path.parts,返回文件所在各级目录拆分成的元组。
- Path.stem,获取文件名不包含后缀名。
- Path.suffix,获取文件的后缀名。
- Path.anchor,获取文件所在的盘符。
from pathlib import Path
txtPath = Path('python-100.txt')
nowPath = txtPath.resolve()
print("文件的完整路径为:%s" % nowPath)
print("文件完整名称为(文件名+后缀名):%s" % nowPath.name)
print("文件名为:%s" % nowPath.stem)
print("文件后缀名为:%s" % nowPath.suffix)
print("文件所在的文件夹名为:%s" % nowPath.parent)
print("文件所在的盘符为:%s" % nowPath.anchor)
3.6 文件、路径是否存在判断
- Path.exists(),判断 Path 路径是否指向一个已存在的文件或目录,返回 True 或 False。
- Path.is_dir(),判断 Path 是否是一个路径,返回 True 或 False。
- Path.is_file(),判断 Path 是否指向一个文件,返回 True 或 False。
from pathlib import Path
currentPath = Path.cwd() / 'python'
print(currentPath.exists()) # 判断是否存在 python 文件夹,此时返回 False。
print(currentPath.is_dir()) # 判断是否存在 python 文件夹,此时返回 False。
currentPath.mkdir() # 创建 python 文件夹。
print(currentPath.exists()) # 判断是否存在 python 文件夹,此时返回 True。
print(currentPath.is_dir()) # 判断是否存在 python 文件夹,此时返回 True。
currentPath = Path.cwd() / 'python-100.txt'
print(currentPath.exists()) # 判断是否存在 python-100.txt 文件,此时文件未创建返回 False。
print(currentPath.is_file()) # 判断是否存在 python-100.txt 文件,此时文件未创建返回 False。
f = open(currentPath,'w') # 创建 python-100.txt 文件。
f.close()
print(currentPath.exists()) # 判断是否存在 python-100.txt 文件,此时返回 True。
print(currentPath.is_file()) # 判断是否存在 python-100.txt 文件,此时返回 True。
3.7 文件统计以及匹配查找
- Path.iterdir(),返回 Path 目录文件夹下的所有文件,返回的是一个生成器类型。
- Path.glob(pattern),返回 Path 目录文件夹下所有与 pattern 匹配的文件,返回的是一个生成器类型。
- Path.rglob(pattern),返回 Path 路径下所有子文件夹中与 pattern 匹配的文件,返回的是一个生成器类型。
# 使用 Path.iterdir() 获取当前文件下的所有文件,并根据后缀名统计其个数。
import pathlib
from collections import Counter
currentPath = pathlib.Path.cwd()
gen = (i.suffix for i in currentPath.iterdir())
print(Counter(gen))
import pathlib
from collections import Counter
currentPath = pathlib.Path.cwd()
gen = (i.suffix for i in currentPath.glob('*.txt')) # 获取当前文件下的所有 txt 文件,并统计其个数。
print(Counter(gen))
gen = (i.suffix for i in currentPath.rglob('*.txt')) # 获取目录中子文件夹下的所有 txt 文件,并统计其个数。
print(Counter(gen))
glob()方法的高阶用法
glob 模块提供对 Unix shell 样式通配符的支持,这些通配符与正则表达式(在 re 模块中记录)不同。
glob支持 *?[]
三种通配符:
*
匹配 0 个或多个字符;?
匹配单个字符;[]
匹配指定范围内的字符,如:[0-9]匹配数字,[a-z]匹配字母;[seq]
匹配任何在 seq 中的字符;[!seq]
匹配任何不在 seq 中的字符。
应用示例:
假设示例目录如下:
|-- dir
|-- file1.txt
|-- file2.txt
|-- filea.txt
|-- fileb.txt
|-- subdir
|-- subfile.txt
- 匹配所有文件
import glob
for name in glob.glob('dir/*'):
print(name)
""" Output
dir/file1.txt
dir/file2.txt
dir/filea.txt
dir/fileb.txt
dir/subdir
"""
- 单字节通配符匹配
for name in glob.glob('dir/file?.txt'):
print(name)
""" Output
dir/file1.txt
dir/file2.txt
dir/filea.txt
dir/fileb.txt
"""
- 字符区间匹配
# method 1
for name in glob.glob('dir/*[0-9].*'):
print(name)
# method 2
for name in glob.glob('dir/*[12].*')
print(name)
# method 3
for name in glob.glob('dir/*[!ab].*')
print(name)
""" Output
dir/file1.txt
dir/file2.txt
"""
4.shutil操作文件
4.1复制文件
这是比较常用的功能
1.shutil.copy()
copy() 方法的功能类似于 Unix 中的“cp”命令。这意味着如果目标是一个文件夹,那么它将在其中创建一个与源文件具有相同名称(基本名称)的新文件。此外,该方法会在复制源文件的内容后同步目标文件权限到源文件。
copy() 还可以在复制内容时设置权限位,而 copyfile() 只复制数据。
#返回值是复制之后的路径
shutil.copy('来源文件','目标地址')
2.shutil.copy2()
虽然 copy2() 方法的功能类似于 copy()。但是复制后的结果保留了原来的所有信息(包括状态信息)。复制相同的文件会导致 SameFileError 异常。
3.shutil.copyfile()
将一个文件的内容拷贝的另外一个文件当中
#返回值是复制之后的路径
shutil.copyfile(来源文件,目标文件)
4.shutil.copyfileobj()
将一个文件的内容拷贝的另外一个文件当中
(用的比较少)
shutil.copyfileobj(open(来源文件,'r'),open('目标文件','w'))
5.shutil.copytree()
复制整个文件目录
(无论文件夹是否为空,均可以复制,而且会复制文件夹中的所有内容)
shutil.copytree(来源目录,目标目录)
4.2 删除文件
1.shutil.rmtree()
(删除的是文件夹,如果删除文件os.unlink(path)
)
移除整个目录,无论是否空
shutil.rmtree(目录路径)
4.3 移动文件
move()
shutil.move(来源地址,目标地址)