【Python】-8.Python文件与IO


1. 打开文件

在Python中无论是从文件中读取内容还是把内容写到文件,都需要先打开文件。打开文件使用内置函数 open

open 函数有许多参数,它的定义如下:

def open(file, mode=’r’, buffering=None, encoding=None, errors=None, newline=None, closefd=True)

open 只有file参数是必传的,其他参数都由默认值。

file_name = "1.打开文件.py"
f = open(file_name)
print(f)

1.1 文件模式

open的mode参数十分重要,它指明了要以何种方式打开文件。使用不同的方式打开文件,即使操作相同,产生的效果也会不同。

默认模式是 “r”,即以只读的方式打开文件,文件只能读但不能写。

文件模式:r、rb、r+、rb+、w、wb、w+、wb+、a、ab、a+、ab+

访问模式 说明
r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
w 打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。
wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
r+ 打开一个文件用于读写。文件指针将会放在文件的开头。
w+ 打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
wb+ 以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
ab+ 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

Python 读写文件时会区分二进制和文本两种方式。如果以二进制方式打开文件,内容将作为字节对象返回,不会对文本内容进行任何编码;如果以文本方式打开文件,内容将作为字符串对象返回,文件内容会根据平台相关的编码或指定了的 “encoding” 参数的编码进行解码。

1.2 文件编码

在文本方式下,如果没有指定编码,Python解释器会根据不同的系统使用不同的编码来解码文件。默认情况下,Python会调用标准库locale的getpreferredencoding方法来获取系统的默认编码,以作为文本方式解码文件内容的编码。

一般情况下,为了防止乱码,使用 UTF-8作为默认编码。

1.3 文件缓冲

缓冲的目的是减少系统 IO 的调用,只有在复合一定条件之后系统才调用 IO 写入磁盘
缓冲参数 buffering 使用用友设置缓冲策略的可选参数。

缓冲参数取值:

  • 0 — 关闭缓冲;
  • 1 — 选择行缓冲;
  • 大于1 — 指定缓冲区大小(以字节为单位);

如果没有指定缓冲参数,则以默认缓冲策略的方式工作。缓冲取的大小为 io.DEFAULT_BUFFER_SIZE 字节,一般为 4096 或者 8192

2. 文件基本操作

2.1 读文件

readme.txt

写入文件

2.1.1 使用read读取文件内容

f = open("readme.txt")
txt = f.read()
print(txt) # 写入文件

2.1.2 read读取指定长度

f = open("readme.txt")
txt = f.read(20)  # 2.读取20个字符
print(txt) # 写入文件

2.2 写文件

2.2.1 使用 “w” 模式写入文件

write 方法返回写入文件的字符串的长度

f = open("readme.txt", "w")
txt = "写入文件"
print(f.write(txt)) # 4

2.2.2 使用 “a” 模式追加文件

from datetime import datetime

f = open("append.txt", "a")
now = str(datetime.now()) + "\n"
print(f.write(now)) # 27

2.3 按行读文件

2.3.1 使用readline按行读取

文件很大、文件内容很多的时候,可以使用按行读取 readline

f = open("append.txt", "r")
print(f.readline()) # 2020-08-02 14:40:48.575777
print(f.readline()) # 2020-08-02 14:40:59.191706

2.3.2 使用 readlines 读取所有行

readlines 读取整个文件,返回一个列表

f = open("append.txt", "r")

for line in f.readlines():
    print(line)

# 2020-08-02 14:40:48.575777
# 2020-08-02 14:40:59.191706
# 2020-08-02 14:42:11.297548
# 2020-11-21 15:36:30.757284

2.3.3 迭代文件对象

迭代文件对象是一种 “惰性” 的读取方式,只有迭代到需要读取的一行,才会真正执行读取操作

f = open("append.txt", "r")

for line in f:
    print(line)

# 2020-08-02 14:40:48.575777
# 2020-08-02 14:40:59.191706
# 2020-08-02 14:42:11.297548
# 2020-11-21 15:36:30.757284

2.4. 按行写文件

2.4.1 使用 writelines 方法按行写入文件

使用 writelines 方法按行写入文件,writelines 接收一个列表对象,同时不会添加换行符

f = open("writelines.txt", "w")
lines = []
for i in range(10):
    lines.append(str(i))

f.writelines(lines)

writelines.txt

0123456789

2.5 关闭文件

2.5.1 使用 close 关闭

文件读写完毕,或者出现异常时需要关闭。使用 close 方法

f = open("writelines.txt", "w")
f.close()

2.5.2 在 finally 中关闭

f = None
try:
    f = open("readme.txt", "r")
    print(f.read()) # 写入文件
except IOError:
    print("Error")
finally:
    f.close()

2.5.3 使用 with 自动关闭

with open("readme.txt", "r") as f:
    content = f.read()
    print(content) # 写入文件

3. StringIO和BytesIO

Python 对应文件的读取和写入,有时并不需要真正写入文件中,只需要在内存中做读写即可。

Python 的 IO 模块提供给了操作 str 的 StringIO 函数

3.1 StringIO

3.1.1 创建 StringIO 对象

from io import StringIO

f = StringIO()
f.write("hello")
f.write(" ")
f.write("world")
print(f.getvalue()) # hello world

3.1.2 使用字符串初始化 StringIO

f = StringIO("Hello!\nWorld!\nWelcome!")
while True:
    s = f.readline()
    if s == '':
        break
    print(s.strip())

# Hello!
# World!
# Welcome!

3.2 BytesIO

3.2.1 BytesIO 实现了内存中读写 bytes

from io import BytesIO

f = BytesIO()
f.write("您好".encode("utf-8"))
print(f.getvalue()) # b'\xe6\x82\xa8\xe5\xa5\xbd'
print(f.getvalue().decode("utf-8")) # 您好

3.2.2 使用bytes初始化 BytesIO

f = BytesIO(b'\xe6\x82\xa8\xe5\xa5\xbd')
print(f.getvalue().decode("utf-8")) # 您好

4. 序列化与反序列化

序列化就是将数据结构或者对象转换成二进制串,反序列化就是将二进制串转回成数据结构或者对象

4.1 pickle 模块

4.1.1 pickle序列化

import pickle

class Student:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

student1 = Student("小明", 15, "男")
print(pickle.dumps(student1))
# b'\x80\x04\x95G\x00\x00\x00\x00\x00\x00\x00\x8c\x08__main__\x94\x8c\x07Student\x94\x93\x94)\x81\x94}\x94(\x8c\x04name\x94\x8c\x06\xe5\xb0\x8f\xe6\x98\x8e\x94\x8c\x03age\x94K\x0f\x8c\x06gender\x94\x8c\x03\xe7\x94\xb7\x94ub.'

4.1.2 将序列化的结果保存到文件

class Student:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

student1 = Student("小红", 18, "女")

with open("student1.data", "wb") as f:
    pickle.dump(student1, f)

4.1.3 反序列化

class Student:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender =gender

f = open("student1.data", "rb")
data = f.read()
student1 = pickle.loads(data)
f.close()

print("姓名", student1.name) # 姓名 小红
print("年龄", student1.age) # 年龄 18
print("性别", student1.gender) # 性别 女

4.1.4 读取文件反序列化

class Student:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

with open("student1.data", "rb") as f:
    student1 = pickle.load(f)
    print("姓名", student1.name) # 姓名 小红
    print("年龄", student1.age) # 年龄 18
    print("性别", student1.gender) # 性别 女

4.2. JSON 序列化和反序列化

json 模块的序列化使用方法和 pickle 一样,但是 pickle 可以序列化任意 Python 对象,而 json 模块只能序列化部分类型

json 可以序列化的类型: dict、list、str、int、float、True、False、None

import json
student1 = {
    "name":"小明",
    "age":15,
    "gender":"男"
}

print(json.dumps(student1))
# {"name": "\u5c0f\u660e", "age": 15, "gender": "\u7537"}

4.2.1 json 序列化结果写入文件

student1 = {
    "name":"小明",
    "age":15,
    "gender":"男"
}

with open("student1.json", "w") as f:
    json.dump(student1, f)

4.2.2 json 反序列化

f = open("student1.json", "r")
data = f.read()
student1 = json.loads(data)
f.close()
print(student1) # {'name': '小明', 'age': 15, 'gender': '男'}

4.2.3 json 读取文件反序列化

with open("student1.json", "r") as f:
    student1 = json.load(f)
    print(student1) # {'name': '小明', 'age': 15, 'gender': '男'}

文章作者: Soulballad
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Soulballad !
评论
 上一篇
【Python】-9.Python日期和时间 【Python】-9.Python日期和时间
1. 基本概念1.1 时间戳时间戳是指格林尼治时间1970年01月01日00时00分00秒(即北京时间1970年01月01日08时00分00秒)到现在的总秒数。 1.2 时间日期格式化符号在Python中会使用到一些特殊的符号来格式化时间日
2020-09-15
下一篇 
【Python】-7.Python中的模块 【Python】-7.Python中的模块
1. 模块1.1 模块介绍 模块是一个包含了Python定义和声明的 “.py” 文件。模块可以被别的程序引入,以使用该模块中的函数等功能。这也是使用 python 标准库的方法。 定义 fibs.py 模块 # fibs.py def
2020-09-12
  目录