深入解读Python文件读写机制与底层实现
本文详细解析Python中文件读写的核心机制。从[[wp:a0]]函数的参数与模式详解入手,涵盖读写、追加及二进制模式;深入讲解文件对象方法如read、write及[[wp:a21]]偏移定位;介绍[[wp:a39]]语句的安全用法;最后对比[[wp:a50]]底层系统调用,揭示Python文件操作的内部原理与性能差异。
深入解读Python文件读写机制
Python提供了便捷的文件读写功能,其中open是执行文件操作的第一步。通过open进行读写的方式,可以类比为将大象装入冰箱的过程:先打开冰箱门(打开文件),再装入大象(写入内容),最后关上冰箱门(关闭文件)。
f = open("test.txt",'w') #第一步,把冰箱门(文件)打开
f.write("this is content") #第二步,把大象(文件内容)装进去
f.close() #第三步,把冰箱门关上,否则大象可能会跑掉
open函数的定义方式如下所示。
file=open(path,mode='r',buffering=-1,encoding=None)
该函数包含多个关键参数:
path指定文件的路径。mode指定读取或写入的模式,默认为r,即只读模式。buffering指定缓冲区大小。由于内存读写速度远快于外设,大多数情况下无需设置,即保持不大于0的默认值。encoding指定文件的编码方式,如UTF-8等。- 函数最终返回一个
file对象,用于后续的文件操作。
在mode模式中,常见的取值包括以下几种。
| r | r+ | w | w+ | a | a+ | |
|---|---|---|---|---|---|---|
| b | rb | rb+ | wb | wb+ | ab | ab+ |
其中,字母b表示二进制模式,r表示读模式,w表示写模式,a表示追加模式。无论选择何种基础模式,若包含+符号,则意味着文件既可读也可写。写入操作通常会覆盖原文件内容,而追加模式则在文件末尾开始写入。如果指定文件不存在,w, w+, a, a+, wb模式会自动创建新文件。
文件对象的方法与属性
通过open创建的文件对象,除了使用close方法关闭文件外,还有两组最常用的函数:用于读取的read和用于写入的write,它们的具体区别如下。
| read | write | 读写整个文件 read(size)可读取size大小的文件 |
| readline | 每次读一行 由于write直接输入字符串,故不必设置writeline |
|
| readlines | writelines | 前者按行读取文件,并存入一个字符串列表 writelines将一个字符串列表的形式写入文件 |
例如,以下代码展示了如何使用这些方法。
>>> f = open('test.txt','w')
>>> f.writelines(['a','b','c\n','d'])
>>> f.close()
>>> f = open('test.txt','r')
>>> f.readlines()
['abc\n', 'd'] #在写lines的时候,并不会自动添加\n
>>> f.close()
根据电脑性能不同,读取500M的txt文件可能需要超过1秒,而读取2G的文件可能会报错。此时可以通过seek函数指定偏移量,从而在文件的特定位置进行读写操作。其输入格式为f.seek(offset,whence=0)。
其中包含两个参数:
offset指定偏移量的数值。whence指定偏移的方式:0表示绝对定位(从头开始),1表示相对定位(从当前位置),2表示从文件末尾定位。
从seek函数的视角来看,在open文件时,如果使用了w模式,则相当于执行seek(0)操作;如果使用了a模式,则相当于执行seek(0,2)操作。
通过tell可以返回当前的文件偏移量,这相当于seek函数的对偶操作。
在完成文件操作后,需要使用f.close()将缓存中的数据写入硬盘;如果担心意外断电或崩溃导致数据丢失,可以使用f.flush()强制立即写入。
此外,文件对象还包含以下成员变量。
| name | mode | encoding | error | closed | buffer |
|---|---|---|---|---|---|
| 文件名 | 读写模式 | 编码方式 | 错误模式 | 是否已经关闭 | 缓冲区 |
另外还有三个判定函数用于检查文件状态。
readable() |
writable() |
seekable |
|---|---|---|
| 是否可读 | 是否可写 | 可否指定偏移量 |
使用with … as语句
在写入文件时,如果忘记调用close或flush,部分数据可能仍留在内存中,导致生成的文件不完整。
with as表达式通过自动调用对象中的__enter__方法和__exit__方法,能够更智能地管理close过程,从而免去了手动编写close的麻烦。其调用语法为。
with open('text.txt','w') as f:
f.write("12345")
查看file.py源码可知,其__exit__函数实际上就是执行close操作。
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self.close()
底层实现:os.open
open虽然使用方便,但开销较大,因为它直接返回了一个完整的文件对象。相比之下,其底层实现os.open返回的是一个整型的文件描述符ID。对于对速度有极高要求的频繁文件读写场景,可以考虑直接使用此底层函数。
在os模块中,打开文件的方法为。
fd = os.open(path, flags, mode=511, dir_fd=None)
该函数包含以下参数:
path指定文件路径。flags指定打开标志,例如os.O_RDONLY代表只读,os.O_WRONLY代表只写。mode表示文件权限,例如777代表任何人可读可写可执行;511代表文件创建者可读可执行,其他人只可读。这属于Linux系统的内容,日后将在Linux专题中详细讨论。dir_fd表示相对路径的规则,为自定义函数,较少使用。- 最后,输出的
fd是某个文件的标识符(文件描述符)。
其中,mode的取值可见于deepin和Windows的手册,常用的标志如下。多个标志可通过|运算符叠加,这种浓郁的C语言风格确认了其直接来自操作系统接口。
| os.open | open | os.open | open |
|---|---|---|---|
| os.O_RDONLY | ‘r' | os.O_WRONLY | ‘w' |
| os.O_RDWR | ‘r+' | os.O_APPEND | ‘a' |
| os.O_CREAT | 创建并打开 |
与相关的其他函数还有:
os.fdopen(fd, mode, bufsize) |
通过fd创建一个文件对象,并返回这个文件对象 |
os.read(fd, n) |
从fd 中读取最多 n 个字节并返回,如果fd对应文件已达到结尾, 则返回空串。 |
os.write(fd, str) |
将str写入fd,返回实际写入的字符串长度 |
os.fsync(fd) |
强制将fd所对应的文件写入硬盘 |
os.close(fd) |
关闭fd |
os.dup(fd) |
复制fd |
os.dup2(fd, fd2) |
将fd1所对应的文件复制给fd2 |
os.fstat(fd) |
返回fd的状态 |
os.ftruncate(fd, length) |
裁剪fd, length不大于文件尺寸 |
os.isatty(fd) |
如果fd已经打开,同时与tty(-like)设备相连,则返回True, 否则False。 |
os.lseek(fd, pos, how) |
设置fd当前位置为pos, how为修改方式,等同于前文中的whence |
到此这篇关于深入解读Python如何进行文件读写的文章就介绍到这了,更多相关Python文件读写内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









