LEMON

记录站

0%

Python文件处理及with语句(八)

Python 文件处理

一、open() 方法

Python open() 方法用于打开一个文件,并返回文件对象,在对文件进行处理过程都需要使用到这个函数,如果该文件无法被打开,会抛出 OSError。

注意:使用 open() 方法一定要保证关闭文件对象,即调用 close() 方法。

  • 格式
1
open(path, mode='r', encoding=None, errors=None, buffering=-1, newline=None)
  • 参数说明:
参数 说明
path 文件路径(相对或者绝对路径)。
mode 文件打开模式;默认为文本模式。
encoding 编码方式,默认就是utf-8
errors 报错处理级别;常用的 ignore(忽略错误)
newline 区分换行符
  • mode 参数有:
模式 描述
t 文本模式 (默认)。
x 写模式,新建一个文件,如果该文件已存在则会报错。
b 二进制模式。
+ 打开一个文件进行更新(可读可写)。
r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。一般用于非文本文件如图片等。
r+ 打开一个文件用于读写。文件指针将会放在文件的开头。
rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。一般用于非文本文件如图片等
w 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。
w+ 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb+ 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。
a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
ab+ 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。
  • file 对象: file 对象使用 open 函数来创建,下表列出了 file 对象常用的函数
方法 描述
file.read() 从文件读取指定的字节数,如果未给定或为负则读取所有。
file.readline() 读取整行,包括 “\n” 字符;同时它也可以读取指定文件字符数
file.readlines()* 读取所有行并以列表的类型返回
file.seek() 设置文件当前位置【修改描述符 (开始点)】
file.write() 将数据以覆盖的形式写入缓冲区(文件),返回的是写入的字符长度。
file.close() 关闭文件。关闭后文件不能再进行读写操作。
file.flush() 刷新缓冲区,直接把内部缓冲区的数据立刻写入文件,而不是被动的等待自动刷新缓冲区写入。 刷新缓冲区的方法有:关闭文件、缓冲区满了、手动刷新、遇到\n换行符
file.writelines() 向文件写一个序列字符串列表,如果需要换行则要自己加入每行的换行符。
file.fileno() 返回一个整型的文件描述符(file descriptor FD 整型), 可以用在如os模块的read方法等一些底层操作上。
file.truncate() 截取文件,截取的字节通过size指定,默认为当前文件位置。
file.isatty() 如果文件连接到一个终端设备返回 True,否则返回 False。
file.next() 返回文件下一行。
file.tell() 返回文件当前位置。

二、对文件的操作的三个步骤

1
2
3
4
5
(1)、打开文件:open

(2)、操作文件:对文件进行读或写 read/write

(3)、关闭文件:close

注:对文件进行读写后,一定不要忘记关闭文件,因为:

  • 文件对象占用操作系统资源;
  • 操作系统能打开的文件总数量有限;
  • 当我们写文件时,操作系统不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。
  • 只有调用 close() 方法时,操作系统才会把没有写入的数据全部写入至磁盘。
  • 忘记调用 close() 的后果是数据可能只写了一部分到磁盘,剩下的丢失了。

三、文件处理—读文件

1. 读文件过程

1
2
3
4
5
1、打开文件

2、读取文件内容

3、关闭文件

2. 简单示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# 1、read() 读取文件全部的内容;这种适合读取较小的文件
path = r"file_path" #文件路径
f = open(path, "r", encoding="utf-8", errors="ignore") #打开文件

str1 = f.read() #读取文件
print(str1)

f.close() #关闭文件



# 2、read(number) 读取指定文件字符数
path = r"file_path"
f = open(path, "r", encoding="utf-8")

str2 = f.read(5) #读取文件5个字符的内容
print(str2)

str3 = f.read(10) #继续读取往后10个字符的内容,换行符\n也算一个字符数
print(str3)

f.close()



# 3、readline() 读取整行,包括 "\n" 字符;同时它也可以读取指定文件字符数
path = r"file_path"
f = open(path, "r", encoding="utf-8")

str4 = f.readline()
print("str4 =", str4)

str5 = f.readline(3)
print("str5 =", str5)

f.close()



# 4、readlines() 读取所有行并以列表的类型返回;包含\n换行符
path = r"file_path"
f = open(path, "r", encoding="utf-8")

list6 = f.readlines()
print(list6)

f.close()



# 5、修改描述符(开始点)
path = r"file_path"
f = open(path, "r", encoding="utf-8")

str7 = f.read()
print(str7)

print("--------------------------")

f.seek(5) # 将描述符放到第5个字符的后面
str8 = f.read()
print(str8)

f.close()

3. 最稳妥的读文件方法

  • 再说一遍:不管执行成不成功,最后必须关闭文件

  • 两种方法:

    • try - finally 语句
    1
    2
    3
    4
    5
    6
    path = r"file_path"
    try:
    f1 = open(path, "r", encoding="utf-8")
    print(f1.read())
    finally: # 不管上面语句执行成不成功,都将执行finally下的语句
    f1.close() # 关闭文件
    • with 语句
    1
    2
    3
    path = r"file_path"
    with open(path, "r", encoding="utf-8") as f2: # with执行到最后会自动退出文件
    print(f2.read())

四、文件处理 — 写文件

1. 写文件过程

1
2
3
4
- 打开要写入的文件路径
- 以写入的方式打开文件
- 写入数据到缓存区
- 关闭文件自动刷新缓存区

2. 简单示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 1、write("data") 将数据以覆盖的形式写入缓冲区
path = r"file_path"
f = open(path, "w", encoding="utf-8") # 以写入的方式打开文件

f.write("my name is a lemon!!!") # 写入数据到缓存区

# while True: # 因为会一直循环,导致执行不到下面关闭文件的程序,所以数据始终写不到文件里面
# pass

f.close() # 关闭文件自动刷新缓存区



# 2、flush()刷新缓冲区
# 直接把内部缓冲区的数据立刻写入文件,而不是被动的等待自动刷新缓冲区写入
# 刷新缓冲区有几种方法?--> 1、关闭文件 2、缓冲区满了 3、手动刷新 4、遇到\n换行符
path = r"file_path"
f = open(path, "w", encoding="utf-8")

f.write("lemon is a very good")

f.flush() # 刷新缓冲区立即将数据写入文件

while True:
pass

f.close() # 即使不关闭文件也能立刻将数据写入到文件,因为循环上层有一个刷新缓冲区的程序



# 3、write("data") 将数据以追加的形式写入缓冲区
path = r"file_path"
f = open(path, "w", encoding="utf-8")

f.write("my name is a lemon~_~")

f.close()

with open(path, "a", encoding="utf-8") as ff:
ff.write("lemon is very cool!")

3. 最稳妥的写文件方法

  • 两种方法:

    • try - finally 语句
    1
    2
    3
    4
    5
    6
    path = r"file_path"
    try:
    f1 = open(path, "w", encoding="utf-8")
    f.write("my name is a lemon~_~")
    finally: # 不管上面语句执行成不成功,都将执行finally下的语句
    f1.close() # 关闭文件
    • with 语句
    1
    2
    3
    path = r"file_path"
    with open(path, "w", encoding="utf-8") as f2: # with执行到最后会自动退出文件
    f.write("my name is a lemon~_~")

五、编码与解码

  • 注:凡是二进制写入的就必须要编码解码
  • encode() :用来编码写入文件
1
2
3
4
path = r"file_path"
with open(path, "wb") as f1:
str = "我的名字叫做{lemon}"
f1.write(str.encode("gbk")) # 以gbk格式进行编码写入文件
  • decode() :用来解码读取文件
1
2
3
4
5
6
7
8
with open(path, "rb") as f2:
data = f2.read()
# 编码:b'\xce\xd2\xb5\xc4\xc3\xfb\xd7\xd6\xbd\xd0\xd7\xf6{lemon}' <class 'bytes'>
print(data, type(data))
# 将gbk类型数据进行解码读写{编码是什么解码就写什么} > (两者必须要一致性)
gc_data = data.decode("gbk")
# 解码:我的名字叫做{lemon} <class 'str'>
print(gc_data, type(gc_data))

六、list-tuple-dict-set的文件操作

概念:写入就相当于编码,读取就相当于解码;注意:只能用于二进制的形式进行写入、读取

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import pickle          # 引入pickle:数据持久化模块 

## 1、list
# 写入
gc_list = [1, 2, 3, "lemon"]
path = r"file_path"
k1 = open(path, "wb")
pickle.dump(gc_list, k1) # 只能使用二进制的格式进行写入
k1.close()

# 读取
f1 = open(path, "rb")
temp_list = pickle.load(f1) # 只能使用二进制的格式进行读取
print(temp_list, type(temp_list)) # [1, 2, 3, 'lemon'] <class 'list'>
f1.close()



## 2、tuple
# 写入
gc_tuple = (1, 2, 3, "lemon")
path = r"file_path"
k2 = open(path, "wb")
pickle.dump(gc_tuple, k2) # 只能使用二进制的格式进行写入
k2.close()

# 读取
f2 = open(path, "rb")
temp_tuple = pickle.load(f2) # 只能使用二进制的格式进行读取
print(temp_tuple, type(temp_tuple)) # (1, 2, 3, 'lemon') <class 'tuple'>
f2.close()



## 3、dict
# 写入
gc_dict = {1: "dgf", 2: "alex", 3: "lemon"}
path = r"file_path"
k3 = open(path, "wb")
pickle.dump(gc_dict, k3) # 只能使用二进制的格式进行写入
k3.close()

# 读取
f3 = open(path, "rb")
temp_dcit = pickle.load(f3) # 只能使用二进制的格式进行读取
print(temp_dcit, type(temp_dcit)) # {1: 'dgf', 2: 'alex', 3: 'lemon'} <class 'dict'>
f3.close()



## 4、set
# 写入
gc_set = set([1, 2, 3, 4, 5])
path = r"file_path"
k4 = open(path, "wb")
pickle.dump(gc_set, k4) # 只能使用二进制的格式进行写入
k4.close()

# 读取
f4 = open(path, "rb")
temp_set = pickle.load(f4) # 只能使用二进制的格式进行读取
print(temp_set, type(temp_set)) # {1, 2, 3, 4, 5} <class 'set'>
f4.close()

With 语句

with是从Python2.5引入的一个新的语法,它是一种上下文管理协议,目的在于从流程图中把 try,except 和finally 关键字 和 资源分配释放相关代码统统去掉,简化 try….except….finlally的处理流程;还可以自动关闭文件、线程锁的自动获取和释放等

  • 处理对象

    • 所以使用with处理的对象必须有__enter__()和__exit__()这两个方法。
    • with通过__enter__方法初始化,然后在__exit__中做善后以及处理异常。
  • 作用

    • with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。
  • 格式

1
2
with expression as target:
语句
  • 参数解释

    • expression 是一个需要执行的表达式;
    • target 是一个变量或者元组,存储的是expression表达式执行返回的结果,可选参数
  • 示例

1
2
3
path = r"/root/lemon.txt"
with open(path, "r") as t1:
print(t1.read())

这里使用了 with 语句,不管在处理文件过程中是否发生异常,都能保证 with 语句执行完毕后已经关闭掉打开的文件句柄。如果使用传统的 try / finally范式,则要使用类似如下代码:

1
2
3
4
5
6
7
path = r"/root/lemon.txt"
somefile = open(path, 'r')
try:
for i in somefile:
print(i)
finally:
somefile.close()
-------------本文结束感谢您的阅读-------------