1、文件IO操作
函数 说明
open 打开
read 读取
write 写入
close 关闭
readline 行读取
readlines 多行读取
open方法
1.0、mode模式
打开一个文件,返回一个文件对象(流对象)和文件描述符。打开文件失败,则返回异常
基本使用:创建一个文件test,然后打开它,用完关闭
f = open("test") # file对象
# windows <_io.TextIOWrapper name='test' mode='r' encoding='cp936'>
# linux <_io.TextIOWrapper name='test' mode='r' encoding='UTF-8'>
print(f.read()) # 读取文件
f.close() # 关闭文件
文件操作中,最常用的操作就是读和写。
文件访问的模式有两种:文本模式和二进制模式。不同模式下,操作函数不尽相同,表现的结果也不一
样。
注:
windows中使用codepage代码页,可以认为每一个代码页就是一张编码表。cp936等同于GBK。
open参数
file
打开或者要创建的文件名。如果不指定路径,默认是当前路径
1.0、mode模式
r 只读打开,文件不存在c1lcNotFound异常,文件存在只读打开
w 只写打开,文件不存在创建全新文件,文件存在只写打开,内容清空,相当于一个新的文件
w不管文件存在否,都可以使用改文件,该文件如同一张白纸从头开始写
默认指针从0开始
a 只写打开,文件不存在创建全新文件,文件存在追加写入
w不管文件仔在否,都从文件的EOF开始追加写入
默认指针从EOF开始
x 文件不存在,文件存在抛FileExistsError异常,文件不存在创建全新文件,从头开始写
t text文本模式,编码有关,不指定编码,默认和当前操作系统默认编码有关
b binary二进制
+ 补充缺失的能力
r+ rt+ 主模式还是起着作用,文本只读打开,变成了文本读写打开
wt wt+ 文件不存在创建,文件存在清空
a+ at+ 如果文件已经存在,在尾部追加
x+ xt+ 文件存在报错,文件不存在创建一个文件,然后添加读写能力
rb+ r+b 以只写的二进制方式打开,添加写的能力
wb+ w+b 以只写的二进制方式打开,添加读的能力
ab+ a+b 以追加二进制的方式,添加读写的能力
xb+ x+b 以创建一个文件能力,补一个写读的能力
文件指针东西
不管是不是文本模式,都是按照字节偏移
seek定位, 开头和结尾
tell告诉你现在的索引位置
文本模式
0 从头开始,只能右移,seek(0)
1 只能是0,原地踏步,不要用
2 EOF,只能是0,拉倒末尾
二进制模式
0 从头开始,只能右移,seek(0)
1
2 seek(0,2) 可正可负可0,但是相对于EOF计算后不能超左边界
0 (0和整数,0从头)
* 1 --当前位置,可正可负
* 2 --EOF,可以为负
1.1、open使用:
1.1、open使用:
!touch test #---->调本地shell命令,仅仅用于ipython和jupyter当中
ls
b str.ipynb untitled3.txt
connect.py test untitled.txt
python文件目录与参数解析.ipynb untitled 第201天-python环境安装部署.ipynb
python线性数据结构.ipynb untitled1.txt 未命名2.ipynb
requirements untitled2.txt 未命名3.ipynb
open('test')
<_io.TextIOWrapper name='test' mode='r' encoding='UTF-8'> #---->#z这个是以文本模式的包装器,以读的方式打开,gbk编码
1.2.0、r只读模式使用:
1.2、只读模式使用:
f = open('test') #f全局变量
f = open('test') #mode='r' readonly,只读方式打开
f
<_io.TextIOWrapper name='test' mode='r' encoding='UTF-8'>
f.fileno() #文件描述符1024
75
f.close() #关闭后不显示文件描述符
f.fileno() #显示已经关闭文件,报错显示
operation on closed file
f
<_io.TextIOWrapper name='test' mode='r' encoding='UTF-8'> #---->#z这个是以文本模式的包装器,以读的方式打开,gbk编码
1.2.1、w写模式(危险慎用):
1.2.1、w写模式(危险慎用):
f = open('test','w') #---->test存在
f.write('abc') #---->写入3个字符
3
f = open('test1','w') #---->创建一个文件test1
f.write('xyz')
3
f.close() #---->关闭以打开文件
1.2.2、r读模式:
1.2.2、读模式:
f = open('test1')
f.close()
'xyz'
内容不存在:
f = open('test1','w') #----->开启w模式后,关闭内容不存在
f.close()
空
1.2.3、a追加写入:
1.2.3、a追加写入:
f2 = open('test2','a') #---->创建一个文件test2
f2.write('abc') #---->写入3个字符
内容存在:
f2 = open('test2','a') #---->打开文件立即关闭
f.close() #---->立即关闭
abc #---->内容存在
追加写入:
f2 = open('test2','a')
f2.write('789')
f2.close()
abc789
1.2.4、x模式
1.2.4、x模式
f3 = open('test2','x') #---->test2文件存在抛异常
File exists: 'test2'
f3 = open('test3','x') #---->test3文件不存在则创建文件
f3.write('ala2a3')
6
f3.close()
1.2.5、t文本模式:
1.2.5、t文本模式:
f4 = open('test3','rt') #---->文件存在,以只读方式显示
f4.read()
abrcrd'
f4 = open('test4','rt') #---->文件不存在报错
No such file or directory: 'test4'
1.2.6、b二进制模式:
1.2.6、b二进制模式:
f4 = open('test4','wt') #---->w文件不存在则创建文件,b以二进制显示
f4.write(b'mn') #---->必须加入编码,不然会报错,read不可读
2
f4.write('啊'.encode()) #---->添加编码
3
f5 = open('test4') #rt 你知道这个里面有几个字符吗?
f5 = open('test4',encoding='utf-8')
f5.read()
'mn啊'
f5.close
f6 = open('test4','ab') #gbk
f6.write('abc'.encode())
3
f6.close()
1.2.7、+补上缺失的能力
1.2.7、+补上缺失的能力
f6 = open('test4','r+') #---->gbk rt+ +补上了写能力
f6.read()
'mn啊abc'
f6.write('zyz')
3
f6.close()
f7 = open('test4', 'w+') #---->w全新文件 +补上了读能力
f7.write('abc')
f7.read()
''
f7.close()
!echo "abcdef" >> test5
f7 = open('test5', 'r+') #---->+补上写的能力
f7.write('123')
3
f7.read() #abcabcdef
'abcdef\n'
f7.close()
123abcdef
f7 = open('test5','r+')
f7.read(7)
'0123456'
f7.write('xyz')
3
f7.close()
0123456789
abcxyz
1.2.8、seek搜索 tell告诉我
1.2.8、seek搜索 tell告诉我
不管用什么模式打开,都是用字节索引
f7 = open('test5', 'r+') #+补上写的能力
f7.seek(7) #--->seek精确在指定的位置进行写入
7
f7.write('123')
f7.close()
0123456123
abcxyz
1.2.9、tell告诉我
1.2.9、tell告诉我
f7 = open('test5','a+')
f7.tell()
17
f7.read()
''
f7.seek(0)
0
f7.read()
'0123456123\nabcxyz'
f7 = open('test5','a+')
f7.tell()
17
f7.seek(20)
20
f7.write('mn')
2
f7.close()
0123456123
abcxyzmn
1.2.10、0 (0和整数,0从头)
文本模式
0 从头开始,只能右移,seek(0)
1 只能是0,原地踏步,不要用
2 EOF,只能是0,拉倒末尾
二进制模式
0 从头开始,只能右移,seek(0)
1
2 seek(0,2) 可正可负可0,但是相对于EOF计算后不能超左边界
0 (0和整数,0从头)
* 1 --当前位置,可正可负
* 2 --EOF,可以为负
1.2.10、0 (0和整数,0从头)
f7 = open('test5','a+b')
f7.tell()
21
f7.read()
b''
f7.seek(1,0)
1
f7.read()
b'1234mn123\nabcxyzmnmn'
f7.seek(15,0) #---->0从头开始
15
f7.read()
b'yzmnmn'
f7.write(b'mnt') #---->b以二进制方式写入
3
f7.close()
01234mn123
abcxyzmnmnmnt
1.2.11、* 2 --EOF,可以为负
f7 = open('test5','a+b')
f7.tell()
24
f7.seek(-20,2)
4
f7.read()
b'4mn123\nabcxyzmnmnmnt'
f7.seek(-24,2)
0
f7.read()
b'01234mn123\nabcxyzmnmnmnt'
f7.seek(1,2)
25
f7.read()
b''
f7.close()
1.2.12、* 1 --当前位置,可正可负
f7 = open('test5','a+b')
f7.seek(-7,1)
18
f7.read()
b'nmnmnt'
f7.seek(2,1)
33
f7.read()
b''
f7.close()
1.2.11、readline换行
换行1:
f7 = open('test5','a+')
f7.readline()
while True:
buffer = f7.read(10)
if not buffer:
break
print(buffer.encode())
b'0123456\nxy'
b'z\nabc\nxyz\n'
b'mn\nrst\n'
换行2:
f7 = open('test5','a+')
while True:
buffer = f7.readline() #---->按行断开
if not buffer:
break
print(buffer.rstrip('\n').encode()) #---->rstript跳过换行符
b'0123456'
b'xyz'
b'abc'
b'xyz'
b'mn'
b'rst'
换行3:
for line in f7.readlines(10):
print(line.rstrip())
0123456
xyz
1.2.12、writeline写入行
write(s),文本模式时,从当前指针处把字符串s写入到文件中并返回写入字符的个数;二进制时将
bytes写入文件并返回写入字节数
writelines(lines),将字符串列表写入文件
filename = 'o:/test.txt'
f = open(filename, 'w+')
lines = ['abc', '123\n', 'magedu'] # 需提供换行符
# for line in lines:
# f.write(line)
f.writelines(lines)
f.seek(0) # 回到开始
print(f.read())
f.close()
f9 = open('test9','w+')
f9.write('abcd') #缓冲区里
4
f9.read() #读取或者seek动了,指针,flush到磁盘
''
abcd #---->显示写入结果
f9 = open('test9','w+')
f9.write('mn')
f9.seek(0)
0
f9.write('zyx')
3
f9.close() #close时候,会调用flush
abcdmn
f9 = open('test9','w+')
f9.writelines('abc')
f9.flush()
abc
f9.writelines(['1','2','3'])
f9.read()
abc123
1.2、ipython使用:
1.1、ipython使用:
(m369-1) [python@centos7.8 test]$ ipython
In [1]: !ls #---->列出所有文件
b test5
connect.py test9
python文件目录与参数解析.ipynb untitled
python线性数据结构.ipynb untitled1.txt
requirements untitled2.txt
str.ipynb untitled3.txt
test untitled.txt
test1 第201天-python环境安装部署.ipynb
test2 未命名2.ipynb
1.2.1、ipython打开文件1
1.1.1、ipython打开文件1
In [2]: f = open('b')
In [3]: f
Out[3]: <_io.TextIOWrapper name='b' mode='r' encoding='UTF-8'>
In [4]: f.fileno()
Out[4]: 12
1.1.2、ipython打开文件2
In [1]: fds = []
In [2]: for i in range(2000):
...: f = open('zhgedu')
...: fds.append(f)
...:
[root@centos7.8 ~]# lsof | grep zhgedu| wc -l
6000
1.3、finally关闭
1.2、finally关闭
f = open('test5')
try:
f.write('zyx')
finally: #---->finally保证能够关闭打开的文件
print('0-----------------')
f.close()
print('------------------')
1.4、上下文管理
1.4.1、上下文管理简介
文件对象这种打开资源并一定要关闭的对象,为了保证其打开后一定关闭,为其提供了上下文支持。
filename = 'o:/test.txt'
with open(filename) as f:
print(1, f.closed)
print(f.write('abcd')) # r模式写入失败,抛异常
print(2, f.closed) # with中不管是否抛异常,with结束时都会保证关闭文件对象
with 文件对象 as 标识符: # 等同于 标识符 = 文件对象
pass # 标识符可以在内部使用
上下文管理
1. 使用with关键字,上下文管理针对的是with后的对象
2. 使用with ... as 关键字
3. 上下文管理的语句块并不会开启新的作用域
1.4、with语句
文件对象上下文管理
1. 进入with时,with后的文件对象是被管理对象
2. as子句后的标识符,指向with后的文件对象
3. with语句块执行完的时候,会自动关闭文件对象
filename = 'o:/test.txt'
f = open(filename)
with f:
print(1, f.closed)
print(f.write('abcd')) # r模式写入失败
print(2, f.closed) # with中不管是否抛异常,with结束时都会关闭文件对象
filename = 'o:/test.txt'
f = open(filename)
with f as f2:
print(f is f2) # True
文件的遍历
类似于日志文件,文件需要遍历,最常用的方式就是逐行遍历。
filename = 'o:/test.txt'
with open(filename, 'w') as f:
f.write('\n'.join(map(str, range(101, 120))))
with open(filename) as f:
for line in f: # 文件对象时可迭代对象,逐行遍历
print(line.encode()) # 带换行符
1.4.2、with 文件对象 as 标识符
with语句1:
with open('test5') as f:
#with文件对象,with进入时,会给你返回一个文件对象引用,如果
你需要请使用as语句
#f指向文件对象
print(f)
print(f.closed)
print('--------------')
<_io.TextIOWrapper name='test5' mode='r' encoding='UTF-8'>
False
--------------
# f = open('test5')
# with 文件对象,在离开with语句块,with语法会调用文件对象的close方法,不管with语句出现什么异常,都可以保证
with语句2:
f = open('test5')
with f as f1: #with文件对象 f1 = f
print(f.closed) #---->close后写不进去,抛异常
print(f1 is f)
f.write('zyz')
print('************')
False
True
not writable
with语句3:
with open('test5') as f: #f文件对象
for line in f: #文件对象是可迭代对象,按行度
print(line.rstrip('\n').encode()) #---->rstrip去掉换行符
print(f.closed)
print('************')
b'0123456'
b'xyz'
b'abc'
b'xyz'
b'mn'
b'rst'
False
************
image-20211016053215962
image-20211016055801859
image-20211016060707571
image-20211016143913900
1.5、文件的遍历
类似于日志文件,文件需要遍历,最常用的方式就是逐行遍历。
filename = 'o:/test.txt'
with open(filename, 'w') as f: #---->with方式打开一个文件,起别名为f
f.write('\n'.join(map(str, range(101, 120)))) #---->对这个文件对象写若干行
with open(filename) as f:
for line in f: # 文件对象时可迭代对象,逐行遍历
print(line.encode()) # 带换行符
2、路径操作1
2.1、os.path模块
# os模块常用函数
from os import path
p = path.join('/etc', 'sysconfig', 'network') # 拼接
print(type(p), p)
print(path.exists(p)) # 存在
print(path.split(p)) # 分割
print(path.dirname(p), path.basename(p)) # 路径和基名
print(path.abspath(''), path.abspath('.')) # 绝对路径
print(path.splitdrive('o:/temp/test')) # windows方法
# 打印父目录
p1 = path.abspath(__file__)
print(p1)
while p1 != path.dirname(p1):
p1 = path.dirname(p1)
print(p1)
os.path模块操作的都是字符串。
2.2、os.path 早期目录操作模块
2.2.1、os.path 早期目录操作模块
1.1、os.path 早期目录操作模块
# 更加高级的封装 pathlib.Path
os.path 早期目录操作模块
更加高级的封装 pathlib.Path windowpath
from os import path #---->操作多数都是路径字符串
import os #模块有一个加载过程,os属于必须加载模块,os.path也属于系统必须加载模块
print(path.join('/etc','sysconfig','network')) #--->当前系统路径分隔符合并\ /
#/etc\sysconfig\network #--->路径的类型
p1 = path.join('/etc','sysconfig','network')
print(type(p1),p1)
#<class 'str'> /etc\sysconfig\network #路径字符串类型
p2 = path.split(p1) #---->split分割符,分割出路径加基名
print(type(p2),p2)
#<class 'tuple'> ('/etc\\sysconfig', 'network') #---->得到两个元组,内部都是字符串
dir,bn = path.split(p1) #---->路径,基名
print(type(dir),type(bn),dir,bn)
#<class 'str'> <class 'str'> /etc\sysconfig network #---->路径与基名都是字符串
print([path.exists('o:/abc')]) #--->o盘中是否有abc这个文件
#[False]
2.2.2、dirname路径
1.2、dirname路径
print(path.dirname(p1))
#/etc\sysconfig #---->提取路径
1.2.1、basename基名
print(__file__) #---->当前正在运行的路径是谁
print(path.dirname(__file__)) #__file__特殊变量表示当前运行模块的路径
print(path.basename(__file__)) #---->文件名称
print('-' * 30) #---->打印分割符
#C:/Users/jackie/PycharmProjects/pythonProject/pythenProject/示例脚本/linux/t5.py
#C:/Users/jackie/PycharmProjects/pythonProject/pythenProject/示例脚本/linux
#t5.py
#------------------------------
2.2.3、abspath绝对路径
1.3、abspath绝对路径
print(path.abspath('.')) #---->显示当前路径的绝对路径
print(path.abspath('./abc.py')) #---->当前路径的绝对路径的字符串
p3 = path.abspath('./abc.py')
print(type(p3),p3)
print(type(p4),p4[-1]) #---->取得文件后扩展名
#C:\Users\jackie\PycharmProjects\pythonProject\pythenProject\示例脚本\linux
#C:\Users\jackie\PycharmProjects\pythonProject\pythenProject\示例脚本\linux\abc.py
#<class 'str'> C:\Users\jackie\PycharmProjects\pythonProject\pythenProject\示例脚本\linux\abc.py
1.3.1、exists判断路径
print(path.exists(p3)) #---->判断p3这个路径是否存在
#False
1.3.2、splitext拆分文本信息
p4 = path.splitext('/tmp/mysql.tar.gz') #---->拆分文本信息
#<class 'tuple'> .gz
2.2.4、isdir是否是目录
1.4、isdir是否是目录
print(path.isdir('D:\sdk')) #--->判断是不是一个目录
print(path.isdir('t3.py')) #--->判断这个t3.py的相对目录是否存在
print(path.dirname(__file__)) #--->查看当前目录
print(path.isdir(path.dirname(__file__))) #---->判断是不是一个目录
print('=' * 30)
print(__file__)
#True
#False
#C:/Users/jackie/PycharmProjects/pythonProject/pythenProject/示例脚本/linux
#==============================
#C:/Users/jackie/PycharmProjects/pythonProject/pythenProject/示例脚本/linux/t5.py
1.4.1、取代码的父路径
import time
pp = __file__
while pp != path.dirname(pp):
time.sleep(2)
pp = path.dirname(pp)
print(pp)
# C:/Users/jackie/PycharmProjects/pythonProject/pythenProject/示例脚本/linux/t5.py
# C:/Users/jackie/PycharmProjects/pythonProject/pythenProject/示例脚本/linux
# C:/Users/jackie/PycharmProjects/pythonProject/pythenProject/示例脚本
# C:/Users/jackie/PycharmProjects/pythonProject/pythenProject
# C:/Users/jackie/PycharmProjects/pythonProject
# C:/Users/jackie/PycharmProjects
# C:/Users/jackie
# C:/Users
# C:/
import time
pp = 'o:/a/b'
while True:
time.sleep(1)
curl = path.dirname(pp)
if curl == pp:
break
pp = curl
print(pp)
#C:/Users/jackie/PycharmProjects/pythonProject/pythenProject/示例脚本/linux/t5.py
# o:/a
# o:/
2.2.5、os模块(系统必须模块)
1.5、os模块(系统必须模块)
os.stat使用:
import os
print(os.stat(__file__)) #--->mode权限,ino信息,size文件大小
#os.stat_result(st_mode=33206, st_ino=4503599627848397, st_dev=2196640174, st_nlink=1, st_uid=0, st_gid=0, st_size=4992, st_atime=1635036322, st_mtime=1635036322, st_ctime=1632293766)
2.2.6、Path类创建路径
2.2.6.1、Path类简介
从3.4开始Python提供了pathlib模块,使用Path类操作目录更加方便。
1.1、初始化
p = Path() # 当前目录, Path()、Path('.')、Path('')
p = Path('a', 'b', 'c/d') # 当前目录下的a/b/c/d
p = Path('/etc', Path('sysconfig'), 'network/ifcfg') # 根下的etc目录
1.2、拼接
操作符/
Path对象 / Path对象
Path对象 / 字符串
字符串 / Path对象
joinpath
joinpath(*other) 在当前Path路径上连接多个字符串返回新路径对象
from pathlib import Path
p = Path()
p = p / 'a'
p1 = 'b' / p
p2 = Path('c')
p3 = p2 / p1
print(p1, p2, p3)
print(p3.parts)
print(p3.joinpath('d', 'e/f', Path('g/h')))
1.3、分解
parts属性,会返回目录各部分的元组
p = Path('/a/b/c/d')
print(p.parts) # 最左边的/是根目录
1.4、父目录
p = Path('/magedu/mysql/install/mysql.tar.gz')
print(p.parent)
for x in p.parents: # 可迭代对象
print(x)
2.2.6.2、Path初始化
6.2.1、Path初始化:
1.1、Path初始化:
from pathlib import Path
p1 = Path() #---->拿到一个路径对象,window窗口路径
print( p1)
#C:\Python\python387\python.exe #C:/Users/jackie/PycharmProjects/pythonProject/pythenProject/示例脚本/linux/t4.py 。
Path2:
from pathlib import Path
Path(),Path('.')
(PosixPath('.'), PosixPath('.'))
Path(),Path('a'),Path('a','b/c','d')
(PosixPath('.'), PosixPath('a'), PosixPath('a/b/c/d'))
Path('a','b/c','/d','e/f','g','mysql.tar.gz').absolute() #绝对路径对象
PosixPath('/d/e/f/g/mysql.tar.gz')
Path('a',Path('b'),Path('c/d','e'), 'f/g',Path('.','h'))
PosixPath('a/b/c/d/e/f/g/h')
6.2.2、Path拼接:
1.2、Path拼接:
p1 = Path()
p1 / 'a/b' / './c' /Path('a','b/c') / 'd/e/f' #---->字符串拼接路径对象
PosixPath('a/b/c/a/b/c/d/e/f'
'a/b' / Path('d/e','f',Path('g/h')) / 'i' #---->字符串拼接路径对象
PosixPath('a/b/d/e/f/g/h/i')
str / Pathobj, Pathobj / str, Pathobj / Pathobj
1.2.1、Path拼接:
p1.joinpath('a','b/c',Path('e/f',Path('g')))
PosixPath('a/b/c/e/f/g')
p2 = p1.joinpath('a','b/c',Path('e/f',Path('g')))
p2
PosixPath('a/b/c/e/f/g')
p2.parts
('a', 'b', 'c', 'e', 'f', 'g')
6.2.3、parts分解
1.3、parts分解
p2.absolute().parts #---->显示绝对路径的每个部分
('/',
'home',
'python',
'.pyenv',
'cache',
'projects',
'test',
'a',
'b',
'c',
'e',
'f',
'g')
cd / #---->切根
/
p2
PosixPath('a/b/c/e/f/g')
p2.absolute()
PosixPath('/a/b/c/e/f/g')
6.2.4、parent父目录
1.4、parent父目录
p2.parts
('a', 'b', 'c', 'e', 'f', 'g')
p2.parent.parent.parent.parent
PosixPath('a/b')
p2.parents[1]
PosixPath('a/b/c/e')
1.4.1、参数解构
print(*p2.parents)
a/b/c/e/f a/b/c/e a/b/c a/b a .
print(*p2.absolute().parents)
/a/b/c/e/f /a/b/c/e /a/b/c /a/b /a /
2.2.6.3、目录组成部分
6.3.1、name
name、stem、suffix、suffixes、with_suffix(suffix)、with_name(name)
name 目录的最后一个部分
suffix 目录中最后一个部分的扩展名
stem 目录最后一个部分,没有后缀
name = stem + suffix
suffixes 返回多个扩展名列表
with_suffix(suffix) 有扩展名则替换,无则补充扩展名
with_name(name) 替换目录最后一个部分并返回一个新的路径
1.1、name(取基名) 、parent(取父目录)、suffix(取文件名后缀)
p3 = p2 / 'mysql.tar.gz'
p3
PosixPath('a/b/c/e/f/g/mysql.tar.gz')
6.3.1.1、with_name替换基名
1.1.1、name(取基名):
p3.name #----->basename
'mysql.tar.gz'
1.1.2、取basename名称:
p3.stem #----->basename中的文件名
'mysql.tar'
1.1.3、parent(取父目录):
p3.parent #----->dirname
PosixPath('a/b/c/e/f/g')
1.1.4、换basename名称:
p3.with_name('mysql.ini') #with换一个basename
PosixPath('a/b/c/e/f/g/mysql.ini')
6.3.1.2、with_suffix替换文件名后缀
1.1.5、取文件后缀:
p3.stem,p3.suffix #----->stem + suffix -> name
('mysql.tar', '.gz')
p3.suffixes
['.tar', '.gz']
1.1.5.1、 替换基名后缀
p3.with_suffix('.xz')
PosixPath('a/b/c/e/f/g/mysql.tar.xz')
p3.with_suffix('.xz').name
'mysql.tar.xz'
p3.with_suffix('.xz').absolute().parts
('/', 'a', 'b', 'c', 'e', 'f', 'g', 'mysql.tar.xz')
p3.with_suffix('.xz')
PosixPath('a/b/c/e/f/g/mysql.tar.xz')
Path('/a/b/c').with_suffix('.zip').with_suffix('.7z').with_name('mysql.ini')
PosixPath('/a/b/mysql.ini')
2.2.6.4、全局方法
6.4.1、cwd显示当前的工作路径
cwd() 返回当前工作目录
home() 返回当前家目录
p = Path('/zhgedu/mysql/install/mysql.tar.gz')
print(p.cwd(), Path.cwd())
print(p.home(), Path.home())
判断方法
exists() 目录或文件是否存在
is_dir() 是否是目录,目录存在返回True
is_file() 是否是普通文件,文件存在返回True
is_symlink() 是否是软链接
is_socket() 是否是socket文件
is_block_device() 是否是块设备
is_char_device() 是否是字符设备
is_absolute() 是否是绝对路径
注意:文件只有存在,才能知道它是什么类型文件
1.2、cwd显示当前的工作路径
cd /home
/home
Path().cwd() #------>显示当前工作路径
Path().cwd(),Path.cwd() ,p3.cwd()
(PosixPath('/home'), PosixPath('/home'), PosixPath('/home'))
(m369-1) [python@centos7.8 test]$ ipython
Python 3.7.7 (default, Jul 16 2021, 12:09:50)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.25.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: from pathlib import Path
In [2]: p1 = Path()
In [3]: p1
Out[3]: PosixPath('.')
In [4]: p1.cwd() #------>显示当前工作路径
Out[4]: PosixPath('/home/python/.pyenv/cache/projects/test')
6.4.2、Path切换路径
1.2.1、Path切换路径
In [5]: p2 = Path('/dev') #------>切换路径
In [6]: p2
Out[6]: PosixPath('/dev')
In [8]: ll /dev
crw-rw---- 1 root 7, 132 10月 25 09:53 vcsa4
crw-rw---- 1 root 7, 133 10月 25 09:53 vcsa5
crw-rw---- 1 root 7, 134 10月 25 09:53 vcsa6
drwxr-xr-x 2 root 60 10月 25 09:53 vfio/
In [8]: p2 / 'block' #------>拼出路径
Out[8]: PosixPath('/dev/block')
6.4.3、is_file判断是否存在
1.3、is_file判断
1.3.1、is.dir
In [11]: p3 = p2 / 'block'
In [12]: p3.is_absolute() #------>显示拼出来的值是否是绝对路径
Out[12]: True
In [14]: p3.is_file() #------>是普通文件吗
Out[14]: False
In [17]: p3.is_dir() #------>是目录文件么
Out[17]: True
In [18]: p3.is_symlink() #------>符号链接么
Out[18]: False
In [19]: p3.is_block_device() #------>是块设备么
Out[19]: False
In [20]: p3.is_char_device() #------>是字符设备么
Out[20]: False
1.3.2、with_name修改目录
In [22]: p3.with_name('disk') #------>替换文件名
Out[22]: PosixPath('/dev/disk')
In [26]: p3.with_name('sda1').is_dir()
Out[26]: False
In [27]: p3.with_name('sda1').is_block_device()
Out[27]: True
1.3.3、is_dir判断
In [29]: p4 = Path('/tmp/mysql.tar.gz')
In [30]: p4
Out[30]: PosixPath('/tmp/mysql.tar.gz')
In [31]: p4.is_dir(),p4.is_file() #----->文件不存在什么类型都不是
Out[31]: (False, False)
In [34]: p4.exists() #----->判断文件是否存在
Out[34]: False
2.2.6.5、绝对路径
resolve() 非Windows,返回一个新的路径,这个新路径就是当前Path对象的绝对路径,如果是软
链接则直接被解析。
absolute() 获取绝对路径。
resolve返回新路径
In [35]: p5 = p3.with_name('stdout')
In [36]: p5
Out[36]: PosixPath('/dev/stdout')
In [38]: p5.is_symlink()
Out[38]: True
In [39]: p5.resolve() #----->解析软连接
Out[39]: PosixPath('/dev/pts/1')
创建t软链接:
In [40]: pwd
Out[40]: '/home/python/.pyenv/cache/projects/test'
(m369-1) [python@centos7.8 test]$ mkdir -pv a/b && touch a/b/t.txt
(m369-1) [python@centos7.8 test]$ ln -sv a/b/t.txt t
(m369-1) [python@centos7.8 test]$ echo teststring > a/b/t.txt
(m369-1) [python@centos7.8 test]$ cat a/b/t.txt
teststring
(m369-1) [python@centos7.8 test]$ cat t
teststring
显示软链接中数据:
In [41]: with open('t') as f:
...: print(f.read())
...:
teststring
In [42]: Path('t')
Out[42]: PosixPath('t')
In [43]: Path('t').absolute()
Out[43]: PosixPath('/home/python/.pyenv/cache/projects/test/t')
2.2.6.6、通配符
通配符
glob(pattern) 通配给定的模式,返回生成器对象
rglob(pattern) 通配给定的模式,递归目录,返回生成器对象
? 代表一个字符
* 表示任意个字符
[abc]或[a-z] 表示一个字符
list(p.glob('test*')) # 返回当前目录对象下的test开头的文件
list(p.glob('**/*.py')) # 递归所有目录,等同rglob
list(p.glob('**/*'))
g = p.rglob('*.py') # 生成器,递归
next(g)
list(p.rglob('*.???')) # 匹配扩展名为3个字符的文件
list(p1.rglob('[a-z]*.???')) # 匹配字母开头的且扩展名是3个字符的文件
其它操作
rmdir() 删除空目录。没有提供判断目录为空的方法
touch(mode=0o666, exist_ok=True) 创建一个文件
as_uri() 将路径返回成URI,例如'file:///etc/passwd'
mkdir(mode=0o777, parents=False, exist_ok=False)
parents,是否创建父目录,True等同于mkdir -p。False时,父目录不存在,则抛出
FileNotFoundError
exist_ok参数,在3.5版本加入。False时,路径存在,抛出FileExistsError;True时,
FileExistsError被忽略
iterdir() 迭代当前目录,不递归
from pathlib import Path
p = Path('o:/a/b/c/d')
p.mkdir(parents=True, exist_ok=True)
(p / 'test').touch()
for x in p.parents[len(p.parents) - 1].iterdir(): # 不支持负索引
if x.is_dir():
print('dir =', x)
elif x.is_file():
print('file =', x)
else:
print('other =', x)
stat 相当于stat命令
lstat 使用方法同stat(),但如果是符号链接,则显示符号链接本身的文件信息
6.6.1、glob通配符
In [3]: from pathlib import Path
In [4]: Path().glob('*') #------->生成器对象
Out[4]: <generator object Path.glob at 0x7fd286772f50>
1.1、查询全局文件:
In [5]: print(*Path().glob('*'))
.python-version requirements b .ipynb_checkpoints untitled.txt untitled 未命名2.ipynb untitled1.txt 未命名3.ipynb connect.py python线性数据结构.ipynb 第201天-python环境安装部署.ipynb untitled2.txt str.ipynb untitled3.txt python文件目录与参数解析.ipynb test test1 test2 test3 test4 test5 test9 zhgedu a t
In [2]: print(*Path().glob('*/*')) #------>一层目录解构
.ipynb_checkpoints/未命名2-checkpoint.ipynb .ipynb_checkpoints/未命名3-checkpoint.ipynb .ipynb_checkpoints/python线性数据结构-checkpoint.ipynb .ipynb_checkpoints/第201天-python环境安装部署-checkpoint.ipynb .ipynb_checkpoints/str-checkpoint.ipynb .ipynb_checkpoints/python文件目录与参数解析-checkpoint.ipynb a/b
In [3]: print(*Path().glob('*/[a-z]*')) #------>一层目录的a-z的解构
.ipynb_checkpoints/python线性数据结构-checkpoint.ipynb .ipynb_checkpoints/str-checkpoint.ipynb .ipynb_checkpoints/python文件目录与参数解析-checkpoint.ipynb a/b
In [14]: print(*Path().glob('**/*')) #------->不固定层次匹配,*Path=参数解构
.python-version requirements b .ipynb_checkpoints untitled.txt untitled 未命名2.ipynb untitled1.txt 未命名3.ipynb connect.py python线性数据结构.ipynb 第201天-python环境安装部署.ipynb untitled2.txt str.ipynb untitled3.txt python文件目录与参数解析.ipynb test test1 test2 test3 test4 test5 test9 zhgedu a t .ipynb_checkpoints/未命名2-checkpoint.ipynb .ipynb_checkpoints/未命名3-checkpoint.ipynb .ipynb_checkpoints/python线性数据结构-checkpoint.ipynb .ipynb_checkpoints/第201天-python环境安装部署-checkpoint.ipynb .ipynb_checkpoints/str-checkpoint.ipynb .ipynb_checkpoints/python文件目录与参数解析-checkpoint.ipynb a/b a/b/t.txt
In [6]: print(*Path().glob('*.txt'))
untitled.txt untitled1.txt untitled2.txt untitled3.txt
In [10]: print(*Path().glob('test*'))
test test1 test2 test3 test4 test5 test9
In [11]: print(*Path().glob('*/*/*.txt'))
a/b/t.txt
6.6.2、rglob递归查找:
1.2、rglob递归查找:
In [19]: print(*Path().rglob('*.txt')) #------>不固定层次下面*.txt
untitled.txt untitled1.txt untitled2.txt untitled3.txt a/b/t.txt
1.3、repr转换呈现出来:
In [25]: p1 = Path('t')
In [26]: p1
Out[26]: PosixPath('t')
In [27]: str(p1) #------>转换为字符进行相加减
Out[27]: 't'
In [28]: p1.name
Out[28]: 't'
In [29]: type(p1.name)
Out[29]: str
In [30]: str(p1) + ',' #------>加转换
Out[30]: 't,'
1.4、强制类型转换:
In [31]: print(p1)
t
In [32]: print(str(p1))
t
In [33]: str(p1).encode()
Out[33]: b't'
In [34]: bytes(p1)
Out[34]: b't'
3、路径操作2
3.1、p.mkdir创建删除目录
创建目录
In [5]: from pathlib import Path
In [2]: p5 = Path('test')
In [3]: p5
Out[3]: PosixPath('test')
In [4]: p5.exists()
Out[4]: True
In [5]: p5.mkdir() #------>创建test目录,前提是test目录不存在
创建目录与子目录
In [7]: Path('x/y/z')
Out[7]: PosixPath('x/y/z')
In [8]: Path('x/y/z').touch() #----->必须有x,y才能创建z
In [9]: Path('x/y/z').mkdir(parents=True) #----->创建父目录
删除z目录
In [11]: Path('x/y/z').rmdir()
创建父目录
In [12]: Path('x/y/z').parent.mkdir(parents=True,exist_ok=True)
创建文件z
In [13]: Path('x/y/z').touch()
uri书写格式
In [14]: Path('x/y/z').absolute().as_uri()
Out[14]: 'file:///home/python/.pyenv/cache/projects/test/x/y/z'
3.2、iterdir迭代出目录
iterdir迭代出dir
In [20]: for x in p5.parent.absolute().iterdir():
...: print(x)
/home/python/.pyenv/cache/projects/test/zhgedu
/home/python/.pyenv/cache/projects/test/a
/home/python/.pyenv/cache/projects/test/t
/home/python/.pyenv/cache/projects/test/x
In [21]: for x in Path().iterdir():
...: print(type(x)str(x),x.name)
<class 'pathlib.PosixPath'> a
<class 'pathlib.PosixPath'> t
<class 'pathlib.PosixPath'> x
In [24]: for x in Path().iterdir():
...: if x.is_dir(): #----->如果是目录
...: print('dir = {}'.format(x.name))
...: elif x.is_file():
...: print('file = {}'.format(x.name))
...: else:
...: print(type(x),str(x),x.name)
dir = .ipynb_checkpoints
dir = a
dir = x
file = test1
file = test2
file = test3
s做软链接
In [27]: !ln -sv s x/y
"x/y/s" -> "s"
In [29]: os.stat('b') #----->通过底层去调用
Out[29]: os.stat_result(st_mode=33204, st_ino=34948797, st_dev=2050, st_nlink=1, st_uid=1000, st_gid=1000, st_size=0, st_atime=1626411361, st_mtime=1626411361, st_ctime=1626411361)
In [30]: Path('b').stat() #----->通过路径进行调用
Out[30]: os.stat_result(st_mode=33204, st_ino=34948797, st_dev=2050, st_nlink=1, st_uid=1000, st_gid=1000, st_size=0, st_atime=1626411361, st_mtime=1626411361, st_ctime=1626411361)
In [33]: os.lstat('t') #------>查看软链接一致
Out[33]: os.stat_result(st_mode=41471, st_ino=35199634, st_dev=2050, st_nlink=1, st_uid=1000, st_gid=1000, st_size=9, st_atime=1635153771, st_mtime=1635153768, st_ctime=1635153768)
4、shutil模块使用
shutil模块
文件拷贝:使用打开2个文件对象,源文件读取内容,写入目标文件中来完成拷贝过程。但是这样丢失
stat数据信息(权限等),因为根本没有复制这些信息过去。
目录复制又怎么办呢?
Python提供了一个方便的库shutil(高级文件操作)。
4.1、copy 复制
copyfileobj(fsrc, fdst[, length])
文件对象的复制,fsrc和fdst是open打开的文件对象,复制内容。fdst要求可写。
length 指定了表示buffer的大小;
copyfile(src, dst, *, follow_symlinks=True)
复制文件内容,不含元数据。src、dst为文件的路径字符串
本质上调用的就是copyfileobj,所以不带元数据二进制内容复制。
copymode(src, dst, *, follow_symlinks=True)
仅仅复制权限。
copystat(src, dst, *, follow_symlinks=True)
复制元数据,stat包含权限
copy(src, dst, *, follow_symlinks=True)
复制文件内容、权限和部分元数据,不包括创建时间和修改时间。
本质上调用的是
copyfile(src, dst, follow_symlinks=follow_symlinks)
copymode(src, dst, follow_symlinks=follow_symlinks)
copy2 比copy多了复制全部元数据,但需要平台支持。
本质上调用的是
copyfile(src, dst, follow_symlinks=follow_symlinks)
copystat(src, dst, follow_symlinks=follow_symlinks)
copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,
ignore_dangling_symlinks=False)
递归复制目录。默认使用copy2,也就是带更多的元数据复制。
src、dst必须是目录,src必须存在,dst必须不存在
ignore = func ,提供一个callable(src, names) -> ignored_names。提供一个函数,它会被调用。src是源目录,names是os.listdir(src)的结果,就是列出src中的文件名,返回值是要被过滤的文件名的set类型数据。
# o:/temp下有a、b目录
def ignore(src, names):
ig = filter(lambda x: x.startswith('a'), names) # 忽略a开头的
return set(ig)
shutil.copytree('o:/temp','o:/tt/o',ignore=ignore)
4.1.1、shutill模块
import shutil
shutil.copyfileobj() #最核心的函数,copy源文件还在,目标是全新创建
shutil.copyfile() #核心函数,操作的路径字符串
shutil.copy() #常用的方法 copyfile copymode stat信息st_mode ->dst
shutil.copy2() #常用copyfile copystat stat -> mode, atime mtime ctime
创建目录解构:
(m369-1) [python@centos7.8 test]$ tree
.
├── a
│ ├── a1.py
│ └── b
│ ├── b1.py
│ ├── c
│ │ ├── c1.txt
│ │ └── c2.py
│ └── t.txt
执行ipython:
复制目录到o:/temp下
In [34]: p1 = Path('a/b/c')
In [35]: p1.mkdir(parents=True) #---->创建父目录
In [36]: import shutil #---->引用模块
In [36]: from pathlib import Path #---->引用模块
In [37]: shutil.copytree('a', 'o:/temp') #---->把a目录复制到o盘下的temp下
Out[37]: 'o:/temp'
删除目录解构:
In [39]: shutil.rmtree('o:/temp/') #rm -rf
查看结果
├── o: #---->已经被删除
复制目录结构到dst中:
In [53]: dst = 'o:/Temp/acopy' #----->acopy必须是不存在的
In [55]: src = 'a'
In [55]: shutil.copytree(src,dst) #----->把src目录拷贝到dst中
├── o:
│ └── Temp
│ └── acopy
│ ├── a1.py
│ └── b
│ ├── b1.py
│ ├── c
│ │ ├── c1.txt
│ │ └── c2.py
│ └── t.txt
定义取消目录结构中.txt文件:
In [55]: def ignore_fn(src, names): #----->不理睬src目录中的名字
...: print(src,names)
...: s = set() #----->设置不理睬名单集合
...: for name in names:
...: if name.endswith('.txt'): #----->endswith以.txt结尾的文件不理睬
...: s.add(name) #----->添加到不理睬名单中
...: return s
复制目录结构:
In [58]: shutil.copytree(src,dst, ignore=ignore_fn)
a ['b', 'a1.py']
a/b ['t.txt', 'c', 'b1.py']
a/b/c ['c1.txt', 'c2.py']
Out[58]: 'o:/Temp/acopy'
文件目录解构:
In [60]: print(*Path('o:/Temp').rglob('*'),sep='\n') #--->rglob当前目录下递归,所有文件解构,并换行
o:/Temp/acopy
o:/Temp/acopy/b
o:/Temp/acopy/a1.py
o:/Temp/acopy/b/c
o:/Temp/acopy/b/b1.py
o:/Temp/acopy/b/c/c2.py
查看结果:
(m369-1) [python@centos7.8 Temp]$ tree
.
└── acopy
├── a1.py
└── b
├── b1.py
└── c
└── c2.py
4.1.2、shutil集合解析式
函数1 ---->互相相同
import shutil #----->添加shutil模块
from pathlib import Path #----->添加Path模块
dst = 'o:/Temp/acopy' #----->设置dst目的目录,acopy必须不存在
src = 'a' #----->需要复制src目录
#shutil.copytree(src,dst) #----->src复制到dst目录中
def ignore_fn(src, names): #----->不理睬src目录中的名字
print(src,names)
s = set() #----->设置不理睬名单集合
for name in names:
if name.endswith('.txt'): #----->endswith以.txt结尾的文件不理睬
s.add(name) #----->添加到不理睬名单中
return s
shutil.copytree(src,dst, ignore=ignore_fn) #----->在不理睬.txt文件情况下,完成目录结构复制
print(*Path('o:/Temp').rglob('*'),sep='\n')#----->rglob当前目录下递归,所有文件解构,并换行
函数2 ---->互相相同
import shutil #----->添加shutil模块
from pathlib import Path #----->添加Path模块
dst = 'o:/Temp/acopy' #----->设置dst目的目录,acopy必须不存在
src = 'a' #----->需要复制src目录
def ignore_fn(src,names):
print(src,names)
return {name for name in names if name.endswith('.txt')}
shutil.copytree(src,dst, ignore=ignore_fn) #----->在不理睬.txt文件情况下,完成目录结构复制
print(*Path('o:/Temp').rglob('*'),sep='\n')#----->rglob当前目录下递归,所有文件解构,并换行
函数3 ---->互相相同
5、ini和json文件处理
6、argparse参数解析和实战