python-读写缓冲区

316 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情


大家好,我是芒果,一名非科班的在校大学生。对C/C++、数据结构、Linux及MySql、算法等领域感兴趣,喜欢将所学知识写成博客记录下来。 希望该文章对你有所帮助!如果有错误请大佬们指正!共同学习交流

作者简介:



关于读写缓冲区

学习Linux我们知道, C语言库函数中的fread, fwrite和系统调用read, write相比, 功能是类似的. 但是 fread/fwrite是带有缓冲区的

Python的文件读写操作, 既可以支持带缓冲区, 也可以选择不带缓冲区.

在使用open函数打开一个文件的时候, 其实还有第三个参数, 可以指定是否使用缓冲区, 以及缓冲区的大小是多少 (查看 help(open) 以及 print(doc) ).

a  = open('Z:/test.txt','r')
print(a.__doc__)
print(help(open))

使用flush方法可以立即刷新缓冲区


操作文件指针

文件具备随机访问能力. 这个过程是通过操作文件指针完成的.

seek: 将文件指针移动到从文件开头算起的第几个字节上. 有两个参数.

第一个参数offset表示偏移的字节数.

第二个参数whence表示偏移量的起始位置在哪. 值为0, 表示从开头计算, 值为1, 表示从当前位置, 值为2, 表示从文件结尾位置.

tell: 获取当前文件指针指向的位置. 返回当前位置到文件开头的偏移量.


文件对象内建属性

image-20220319092256112


with语句和上下文管理器

我们刚才说了, 用完的文件对象, 要及时关闭, 否则可能会引起句柄泄露.

但是如果逻辑比较繁琐, 或者我们忘记了手动调用close怎么办?

def func():
    f = open('Z:/test.txt','r')
    x =10
    if x==10:
        return
    #执行文件操作
    f.close()   #上面提前return,导致内存泄漏

解决:在每一个return前先关闭文件

def func():
    f = open('Z:/test.txt','r')
    x =10
    if x==10:
        f.close()
        return
    #执行文件操作
    f.close()

但是如果抛出异常也会导致文件没有关闭:

def func():
    f = open('Z:/test.txt','r')
    x =10
    a = [1,2,3]
    print(a[100])   #越界:IndexError: list index out of range
    if x==10:
        f.close()
        return
    #执行文件操作
    f.close()
    
func()

C++中使用 "智能指针" 这样的方式来管理内存/句柄的释放, 借助对象的构造函数和析构函数, 自动完成释 放过程.

但是Python中对象的回收取决于GC机制, 并不像C++中时效性那么强.

Python中引入了上下文管理器来解决这类问题.

def func():
    with open('Z:/test.txt','r') as f:  #上下文管理器
        #文件操作
        pass    #空语句

可以更改编码格式:

with open('Z:/test.txt', 'r',encoding='utf-8') as f:
    print(f.readline())

with open('Z:/test.txt', 'r',encoding='utf-8') as f:
    for line in f:
        print(line.strip())
#执行结果:
Mango
hello
world

在with语句块内进行文件操作. 当文件操作完毕之后, 出了with语句之外. 就会自动执行f的关闭操作.

一个支持上下文协议的对象才能被应用于with语句中. 我们将这种对象称为上下文管理器. Python中很多 内置对象都是上下文管理器, 例如文件对象, 线程锁对象等.


文件系统的基础操作

文件路径操作

os.path这个模块中, 包含了一些实用的路径操作的函数

basename:去掉目录路径,返回文件名

dirname:去掉文件名,返回目录路径

import os.path
p = '/aaa/bbb/ccc.txt'
print(os.path.dirname(p))   # /aaa/bbb
print(os.path.basename(p))  #ccc.txt

split:返回(dirname(),basename())的元组

import os.path as path
p = '/aaa/bbb/ccc.txt'
print(path.split(p))    #('/aaa/bbb', 'ccc.txt')

splitext:返回(filename,extension)元组 extension:文件的后缀名

import os.path as path
p = '/aaa/bbb/ccc.txt'
print(path.splitext(p))#('/aaa/bbb/ccc', '.txt')

exists:返回文件是否存在

import os.path as path
p = '/aaa/bbb/ccc.txt'
print(path.exists(p))   #False
p = 'Z:/test.txt'
print(path.exists(p))   #True

分隔

image-20220319092518536


信息

image-20220319092532233


查询

image-20220319092542798