操作文件指针
文件具备随机访问能力. 这个过程是通过操作文件指针完成的.
seek
: 将文件指针移动到从文件开头算起的第几个字节上. 有两个参数.
第一个参数offset表示偏移的字节数.
第二个参数whence表示偏移量的起始位置在哪. 值为0, 表示从开头计算, 值为1, 表示从当前位置, 值为2, 表示从文件结尾位置.
tell
: 获取当前文件指针指向的位置. 返回当前位置到文件开头的偏移量.
文件对象内建属性
with语句和上下文管理器
我们刚才说了, 用完的文件对象, 要及时关闭, 否则可能会引起句柄泄露.
但是如果逻辑比较繁琐, 或者我们忘记了手动调用close怎么办?
deffunc():
f = open('Z:/test.txt','r')
x =10
ifx==10:
return
#执行文件操作
f.close() #上面提前return,导致内存泄漏
解决:在每一个return前先关闭文件
deffunc():
f = open('Z:/test.txt','r')
x =10
ifx==10:
f.close()
return
#执行文件操作
f.close()
但是如果抛出异常也会导致文件没有关闭:
deffunc():
f = open('Z:/test.txt','r')
x =10
a = [1,2,3]
print(a[100]) #越界:IndexError: list index out of range
ifx==10:
f.close()
return
#执行文件操作
f.close()
func()
C++中使用 "智能指针" 这样的方式来管理内存/句柄的释放, 借助对象的构造函数和析构函数, 自动完成释放过程.
但是Python中对象的回收取决于GC机制, 并不像C++中时效性那么强.
Python中引入了上下文管理器来解决这类问题.
deffunc():
withopen('Z:/test.txt','r') asf: #上下文管理器
#文件操作
pass #空语句
可以更改编码格式:
withopen('Z:/test.txt', 'r',encoding='utf-8') asf:
print(f.readline())
withopen('Z:/test.txt', 'r',encoding='utf-8') asf:
forlineinf:
print(line.strip())
#执行结果:
Mango
hello
world
在with语句块内进行文件操作. 当文件操作完毕之后, 出了with语句之外. 就会自动执行f的关闭操作.
一个支持上下文协议的对象才能被应用于with语句中. 我们将这种对象称为上下文管理器. Python中很多内置对象都是上下文管理器, 例如文件对象, 线程锁对象等.
文件系统的基础操作
文件路径操作
os.path这个模块中, 包含了一些实用的路径操作的函数
basename:去掉目录路径,返回文件名
dirname:去掉文件名,返回目录路径
importos.path
p = '/aaa/bbb/ccc.txt'
print(os.path.dirname(p)) # /aaa/bbb
print(os.path.basename(p)) #ccc.txt
split:返回(dirname(),basename())的元组
importos.pathaspath
p = '/aaa/bbb/ccc.txt'
print(path.split(p)) #('/aaa/bbb', 'ccc.txt')
splitext:返回(filename,extension)元组 extension:文件的后缀名
importos.pathaspath
p = '/aaa/bbb/ccc.txt'
print(path.splitext(p))#('/aaa/bbb/ccc', '.txt')
exists:返回文件是否存在
importos.pathaspath
p = '/aaa/bbb/ccc.txt'
print(path.exists(p)) #False
p = 'Z:/test.txt'
print(path.exists(p)) #True
分隔
信息
查询
常用文件系统操作
os模块中包含了很多对文件/目录的基础操作, 参见下表.
walk:生成一个目录树下的所有文件名
- 返回的是一个三元组:当前目录,当前目录下的目录,当前目录含有哪些文件
- 自动完成递归
importos.pathaspath
importos
p = 'Z:/test'
foriteminos.walk(p):
print(item)
#执行结果:
('Z:/test', ['a', 'b'], [])
('Z:/test\\a', ['aa'], [])
('Z:/test\\a\\aa', [], ['aa.txt'])
('Z:/test\\b', ['c'], ['b.txt'])
('Z:/test\\b\\c', [], ['c.txt'])
因为返回的是三元组,所以可以写成: 打印完整路径
base:当前目录
_ 当前目录中含哪些目录,不需要用,所以用占位符代替
files:当前目录含有哪些文件
importos.pathaspath
importos
p = 'Z:/test'
#打印完整路径
forbase,_,filesinos.walk(p):
forfinfiles:
print(base+f)
#执行结果:
Z:/test\a\aaaa.txt
Z:/test\bb.txt
Z:/test\b\cc.txt
remove:删除文件
importos.pathaspath
importos
p = 'Z:/test/'
print(path.exists(p+'b/b.txt')) #True
os.remove(p+'b/b.txt') #删除路径为: Z:/test/b/b.txt文件
print(path.exists(p+'b/b.txt')) #False
listdir:列出当前目录的文件
importos.pathaspath
importos
p = 'Z:/test/'
print(os.listdir(p))#列出当前目录的文件 #['a', 'b']
rmdir:删除目录
注意:这个只能删除空目录
importos.pathaspath
importos
p = 'Z:/test/'
print(path.exists(p+'a')) #True
print(os.listdir(p))#列出当前目录的文件 ['a', 'b']
print(os.rmdir(p+'a')) #报错:空目录不能直接删除 OSError: [WinError 145] 目录不是空的。: 'Z:/test/a'
如果想要删除非空目录:使用shutil模块的rmtree函数
importos.pathaspath
importos
importshutil
p = 'Z:/test/'
print(path.exists(p+'a')) #True
print(os.listdir(p))#列出当前目录的文件 ['a', 'b']
shutil.rmtree(p+'a')
print(os.listdir(p))#列出当前目录的文件 ['b']
文件处理
目录/文件夹
访问/权限
文件描述符操作
注意:
虽然os模块中也提供了open, read, write系列函数, 可以用于读写文件.
内建open返回的是文件对象. os.open返回的是文件描述符.
我们实际使用中仍然更推荐使用内建函数open创建文件对象, 并使用文件对象的读写操作来操作文件. 因为文件对象使用起来更方便一些.