23.Python文件I/O详解open()函数&上下文管理器with...as

Posted 孤寒者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了23.Python文件I/O详解open()函数&上下文管理器with...as相关的知识,希望对你有一定的参考价值。

目录:

每篇前言:


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的主要内容,如果未能解决你的问题,请参考以下文章

文件i/o函数 open/close

[OS-Linux]详解Linux的基础IO ------- 文件描述符fd

[OS-Linux]详解Linux的基础IO ------- 文件描述符fd

linux 标准I/O函数详解

unix环境高级编程——文件i/o

I/O Stream