【例 1】默认打开 "a.txt" 文件。
复制纯文本复制
- file = open("a.txt")
- print(file)
#当前程序文件同目录下没有 a.txt 文件
file = open("a.txt")
print(file)
当以默认模式打开文件时,默认使用 r 权限,由于该权限要求打开的文件必须存在,因此运行此代码会报如下错误:
FileNotFoundError Traceback (most recent call last)
<ipython-input-4-dad991fb07c9> in <module>
----> 1 file=open("a.txt")
2 print(file)
FileNotFoundError: [Errno 2] No such file or directory: 'a.txt'
现在,在程序文件同目录下,手动创建一个 a.txt 文件,并再次运行该程序,其运行结果为:
<_io.TextIOWrapper name='a.txt' mode='r' encoding='cp936'>
可以看到,当前输出结果中,输出了 file 文件对象的相关信息,包括打开文件的名称、打开模式、打开文件时所使用的编码格式。
使用 open() 打开文件时,默认采用 GBK 编码。但当要打开的文件不是 GBK 编码格式时,可以在使用 open() 函数时,手动指定打开文件的编码格式,例如:
file = open("a.txt",encoding="utf-8")
注意,手动修改 encoding 参数的值,仅限于文本文件的形式打开,也就是说,以二进制格式打开时,不能对 encoding 参数的值做任何修改,否则程序会抛出 ValueError 异常,如下所示:
ValueError: binary mode doesn't take an encoding argument
open()是否需要缓冲区
通常情况下、建议大家在使用 open() 函数时打开缓冲区,即不需要修改 buffing 参数的值。
果 buffering 参数值为大于 1 的整数,该整数用于指定缓冲区的大小(单位是字节);如果 buffering 参数的值为负数,则代表使用默认的缓冲区大小。
为什么呢?原因很简单,目前为止计算机内存的 I/O 速度仍远远高于计算机外设(例如键盘、鼠标、硬盘等)的 I/O 速度,如果不使用缓冲区,则程序在执行 I/O 操作时,内存和外设就必须进行同步读写操作,也就是说,内存必须等待外设输入(输出)一个字节之后,才能再次输出(输入)一个字节。这意味着,内存中的程序大部分时间都处于等待状态。
而如果使用缓冲区,则程序在执行输出操作时,会先将所有数据都输出到缓冲区中,然后继续执行其它操作,缓冲区中的数据会有外设自行读取处理;同样,当程序执行输入操作时,会先等外设将数据读入缓冲区中,无需同外设做同步读写操作。
open()函数返回的文件对象常用的属性
成功打开文件之后,可以调用文件对象本身拥有的属性获取当前文件的部分信息,其常见的属性为:
file.name:返回文件的名称;
file.mode:返回打开文件时,采用的文件打开模式;
file.encoding:返回打开文件时使用的编码格式;
file.closed:判断文件是否己经关闭。
举个例子:
复制纯文本复制
- f = open('my_file.txt')
-
- print(f.closed)
-
- print(f.mode)
-
- print(f.encoding)
-
- print(f.name)
# 以默认方式打开文件
f = open('my_file.txt')
# 输出文件是否已经关闭
print(f.closed)
# 输出访问模式
print(f.mode)
#输出编码格式
print(f.encoding)
# 输出文件名
print(f.name)
程序执行结果为:
False
cp936
my_file.txt
注意,使用 open() 函数打开的文件对象,必须手动进行关闭python 垃圾回收机制无法自动回收打开文件所占用的资源。
利用文件对象关闭文件——file.close()
with ... as ...上下文管理器打开文件
使用 with as 操作打开的文件对象(本身就是上下文管理器),无论期间是否抛出异常,都能保证 with as 语句执行完毕后自动关闭已经打开的文件。
首先学习如何使用 with as 语句。with as 语句的基本语法格式为:
with 表达式 [as target]:
此格式中,用 [ ] 括起来的部分可以使用,也可以省略。其中,target 参数用于指定一个变量,该语句会将 expression 指定的结果保存到该变量中。with as 语句中的代码块如果不想执行任何语句,可以直接使用 pass 语句代替。
举个例子,假设有一个 a.txt 文件,其存储内容如下:
C语言中文网
http://c.biancheng.net
在和 a.txt 同级目录下,创建一个 .py 文件,并编写如下代码:
- with open('a.txt', 'a') as f:
- f.write("\nPython教程")
with open('a.txt', 'a') as f:
f.write("\nPython教程")
运行结果为:
C语言中文网
http://c.biancheng.net
Python教程
with open("a.txt") as fr,open("b.txt",mode="w") as fw:
fw.writelines(fr.readlines( ))
with open("a.txt") as fr:
with open("b.txt",mode="w") as fw:
fw.writelines(fr.readlines( ))
可以看到,通过使用 with as 语句,即便最终没有关闭文件,修改文件内容的操作也能成功。
(了解)简单的理解,同时包含 __enter__() 和 __exit__() 方法的对象就可以使用with as上下文管理器。文件对象内部实现了__enter__() 和 __exit__() 方法
__enter__(self):进入上下文管理器自动调用的方法,该方法会在 with as 代码块执行之前执行。如果 with 语句有 as子句,那么该方法的返回值会被赋值给 as 子句后的变量;该方法可以返回多个值,因此在 as 子句后面也可以指定多个变量(多个变量必须由“()”括起来组成元组)。
__exit__(self, exc_type, exc_value, exc_traceback):退出上下文管理器自动调用的方法。该方法会在 with as 代码块执行之后执行。如果 with as 代码块成功执行结束,程序自动调用该方法,调用该方法的三个参数都为 None:如果 with as 代码块因为异常而中止,程序也自动调用该方法,使用 sys.exc_info 得到的异常信息将作为调用该方法的参数。