23.Python文件I/O详解open()函数&上下文管理器with...as
Posted 孤寒者
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了23.Python文件I/O详解open()函数&上下文管理器with...as相关的知识,希望对你有一定的参考价值。
目录:
每篇前言:
🏆🏆作者介绍:【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领域博主、CSDN原力计划作者
- 🔥🔥本文已收录于Python全栈系列专栏:《Python全栈基础教程》
- 🔥🔥热门专栏推荐:《Django框架从入门到实战》、《爬虫从入门到精通系列教程》、《爬虫高级》、《前端系列教程》、《tornado一条龙+一个完整版项目》。
- 📝📝本专栏面向广大程序猿,为的是大家都做到Python从入门到精通,同时穿插有很多很多习题,巩固学习。
- 🎉🎉订阅专栏后可私聊进一千多人Python全栈交流群(手把手教学,问题解答); 进群可领取Python全栈教程视频 + 多得数不过来的计算机书籍:基础、Web、爬虫、数据分析、可视化、机器学习、深度学习、人工智能、算法、面试题等。
- 🚀🚀加入我一起学习进步,一个人可以走的很快,一群人才能走的更远!
Python文件I/O(一)
1.1 基本方法
1.1.1 打开和关闭文件
用open()函数打开一个文件,创建一个file对象,调用相关的方法即可对文件进行读写。
完整的语法格式为:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True)
参数说明:
- file: 必需,文件路径(可以是绝对路径,也可以是相对路径)。
- mode: 可选,文件打开模式。
- buffering: 寄存区的缓冲大小。设为0,不会有寄存。设为负值,寄存区的缓冲大小则为系统默认。默认寄存区的缓冲大小为0。
- encoding: 一般使用utf8。
- errors: 报错级别。
- newline: 区分换行符。
- closefd: 传入的file参数类型。
mode具体参数列表:
总结:
-
加个b的作用:以二进制的格式打开文件(比如操作音频文件,图片文件,视频文件…),进行上述操作。
1.1.2 file对象的属性
以下是和file对象相关的所有属性的列表:
-
file 对象的 close()方法刷新缓冲区里任何还没写入的信息,并关闭该文件,这之后便不能再进行写入。
-
当一个文件对象的引用被重新指定给另一个文件时,Python 会关闭之前的文件。用 close()方法关闭文件是一个很好的习惯。
-
注意:打开一个文件操作完之后,一定要关闭。
1.1.3 知识点补给站
- windows系统中:
相对路径:不带盘符的。
绝对路径:带盘符的。 - 光标位置:
1.如果读完了就读不了了,因为光标的位置在最后
2.通过seek方法重新调整光标的位置
3.写完了后,光标位置在最后
例子看看:
f = open(r’ceshi.py’,‘r+’)
f.read()
‘wumou love zhangmou’
f.read() #现在就读不了了,因为光标在上一次读完之后移动到了最后。
‘’
f.seek(0) #把光标位置调整到最前面,那么光标后面就有内容了
0
f.read() #现在就可以读到内容了
‘wumou love zhangmou’
f.tell() #可以查看光标的位置
24
f.seek(0)
0
f.tell()
0
上述方法下一小节会细讲~
1.1.4 文件基本读写与定位
-
write()方法可将任何字符串写入一个打开的文件。
语法:fileObject.write(string)
-
read()方法从一个打开的文件中读取指定长度的字符串(括号里加要读的指定的字符串长度,不写则全读)。
语法:fileObject.read([count])
-
tell()描述文件当前位置
语法:fileObject.tell()
-
seek()改变当前文件的位置
语法:seek(offset [,from])
参数:
offset变量表示要移动的字节数
from变量指定参考位置。0,表示开头。1,表示当前的位置。2,表示末尾(默认为0)
例如:
seek(x,0)
: 从起始位置即文件首行首字符开始移动 x 个字符
seek(x,1)
: 表示从当前位置往后移动x个字符
seek(-x,2)
:表示从文件的结尾往前移动x个字符
实战讲解:
# -*- coding: utf-8 -*-
"""
__author__ = 小小明-代码实体
"""
# 以二进制格式打开一个文件用于读写.如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
fo = open("foo.txt", "wb+")
# 向文件写入2句话
fo.write(b"blog.xiaoxiaoming.xyz!\\nVery good site!\\n")
seq = [b"blog.xiaoxiaoming.xyz!\\n", b"Very good site!"]
fo.writelines(seq)
# 查找当前位置
print("当前文件位置 : ", fo.tell())
# 写完数据,文件指针在文件末尾,现在重定向到文件开头
fo.seek(0)
# 读取10个字符
print("当前文件位置 : ", fo.tell())
str = fo.read(10)
print("读取的字符串是 : ", str)
print("当前文件位置 : ", fo.tell())
# 关闭打开的文件
fo.close()
foo.txt文件内容:
1.1.5 close()
处理完一个文件后, 调用 f.close() 来关闭文件并释放系统的资源,如果尝试再调用该文件,则会抛出异常。
>>> f.close()
>>> f.read()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ValueError: I/O operation on closed file
当处理一个文件对象时, 使用 with 关键字是非常好的方式。在结束后, 它会帮你正确的关闭文件。 而且写起来也比 try - finally 语句块要简短:
>>> with open('/tmp/foo.txt', 'r') as f:
... read_data = f.read()
>>> f.closed
True
1.1.6 file(文件)的方法
file 对象使用 open 函数来创建,下表列出了 file 对象常用的函数:
- 调用read()会一次性读取文件的全部内容,如果文件有10G,内存就爆了,所以,要保险起见,可以反复调用read(size)方法,每次最多读取size个字节的内容。
- 调用next()或readline()可以每次读取一行内容,f.next() 逐行读取数据,和f.readline() 相似,唯一不同的是,readline() 读取到最后如果没有数据会返回空,而next() 没读取到数据则会报错。
- 调用readlines()一次读取所有内容并按行返回list。因此,要根据需要决定怎么调用。
- 如果文件很小,read()一次性读取最方便;如果不能确定文件大小,反复调用read(size)比较保险;如果是配置文件,调用readlines()最方便。
可能有小伙伴不是很理解flush()的作用,其实我们可以浅显的将它的作用理解为保存。下面来个代码讲解一下:
举个例子:
文件内容是: wumou
>> f1 = open('ceshi.py','a')
>> f1.write('shuai')
5
>> f2 = open('ceshi.py','r')
>> f2.read() #会发现现在读是读不到刚刚以追加方式写进入的内容shuai
'wumou'
>> f1.flush() #我们立即刷新缓冲,那么下面就可以读到了。此处作用相当于在进行文件操作之后进行保存
>> f2.seek(0)
0
>> f2.read()
'wumoushuai'
实战讲解:
- 创建tmp.txt文件内容为:
- 上代码:
# -*- coding: utf-8 -*-
"""
__author__ = 小小明-代码实体
"""
fo = open("tmp.txt", "r", encoding="utf-8")
# 立即刷新缓冲区 ——> 可以理解为保存
fo.flush()
print("文件名为: ", fo.name)
print("文件描述符为: ", fo.fileno())
print("文件连接到一个终端设备:", fo.isatty())
# next返回文件下一行
for index in range(5):
line = fo.readline()
print("第 %d 行 - %s" % (index + 1, line), end="")
print()
fo.seek(0)
for line in fo.readlines():
print(line, end="")
# 关闭文件
fo.close()
总结:
- 持久存储:保存内存中数据都是易丢失的,只有保存在硬盘中才能持久的存储,保存在硬盘中的基本方法就是把数据写入文件中。
- 打开和关闭:在python中文件的打开与关闭变得十分简单快捷,文件在关闭的时候就会自动保存。
1.1.7 上下文管理 with…as
每次都写try … finally来关闭文件实在太繁琐,所以,Python引入了with语句来自动帮我们调用close()方法,代码如下:
with open("tmp.txt", encoding="utf-8") as f:
for line in f:
print(line, end="")
- 作用:
让python自动执行关闭过程,即调用close()方法。
管理多个文件自动关闭。
首先来看,单个文件操作时:
# -*- coding: utf-8 -*-
"""
__author__ = 孤寒者
"""
with open(file_path, mode='r') as f:
# 对f进行一系列操作
# 也可以执行别的操作
# 跳出with语句的时候自动执行f.close()
然后来看,多个文件操作时:
# -*- coding: utf-8 -*-
"""
__author__ = 孤寒者
"""
with open(file_path, mode='r') as f1,\\
open(file_path, mode='r') as f2,\\
.
.
.
open(file_path, mode='r') as fn:
# 对f进行一系列操作
# 也可以执行别的操作
file.closed 查看文件是否关闭了
# 跳出with语句块的时候自动执行f.close()
最后来看看:
两个底层方法:__enter__
和__exit__
# -*- coding: utf-8 -*-
"""
__author__ = 孤寒者
"""
class Person:
def __enter__(self): # 进入的时候自动调用
print('this is enter')
return '吴某好帅'
def __exit__(self,exc_type,exc_val,exc_tb): #退出的时候自动调用
print("this is exit")
#with可以打开类,进行多个方法的管理
a = Person()
with a as f: #with可以管理多个软件,打开多个软件。
print(111) #我们打开这个类,就会自动调用__enter__方法,然后进行打印111的操作
print(f) #f就是__enter__的返回值
#结束之后就会自动调用__exit__方法
以上是关于23.Python文件I/O详解open()函数&上下文管理器with...as的主要内容,如果未能解决你的问题,请参考以下文章
[OS-Linux]详解Linux的基础IO ------- 文件描述符fd