pyhton笔记-IO编程

文件IO

open

python内置函数,需要手动关闭文件

1
2
3
4
5
6
try:
f = open('/xxxx/xxx/abc.txt', 'r')
print(f.read()) # read 方法一次读取文件所有内容到内存
finally:
if f:
f.close() # 每次都要手动关闭文件

with…open…

自动关闭文件

1
2
3
4
5
6
with open('path/to/file', 'r') as f:
print(f.read()) # 一次性读取全部内容
# readline() 每次读取一行
# readlines() 一次性读取所有内容并返回list
for line in f.readlines():
print(line.strip()) # 去除每行结尾的\n

file-like object

open()函数返回的,有个read()方法的对象,在python中统称file-like object.除了file,还可以是内存字节流,网络流,自定义流等.file-like object不要求从特定类继承,只要有个read()方法即可.

二进制文件

要读取二进制文件,比如图片,视频等,用'rb'模式打开文件即可

1
2
f = open('path/to/image', 'rb')
f.read()

字符编码

1
2
3
# 通过encoding参数定义
f = open('path/to/gbk', 'r', encoding='gbk', errors='ignore')
# error参数表示遇到编码错误后怎么处理

写文件

通过wwb模式来打开文件,表示写入文本文件或二进制文件

1
2
3
4
5
f = open('path/to/file', 'w')
f.write('hello world')
f.close()
# 系统不会立即把数据写入磁盘,而是先放到内存,空闲时才慢慢写入
# 调用close方法时,系统才保证把没有写入的数据全部写入磁盘
1
2
with open('path/to/file', 'w') as f:
f.write('Hello world')

StringIO

在内存中读写IO,就是一种file-like object.要实现在内存中读写,首先要创建一个StringIO,然后像文件一样写入即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 写
>>> from io import StringIO
>>> f = StringIO()
>>> f.write('hello')
5
>>> f.write(' ')
1
>>> f.write('world!')
6
>>> print(f.getvalue()) # getvalue()用于获取写入后的str
hello world!
# 读
from io import StringIO
f = StringIO('Hello!\nHi!\nGoodbye!')
while True:
s = f.readline()
if s == '':
break
print(s.strip())

BytesIO

StringIO只能操作str,如果要操作二进制,则要用BytesIO

文件目录操作

os模块可以直接调用操作系统提供的接口函数

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
import os
os.name # 操作系统类型
>>> posix # linux/unix/macOSx
>>> nt # windows

os.environ # 系统定义的环境变量,全部保存在这个变量中
os.environ.get('key')

# 查看目录绝对路径
os.path.abspath('.')
# 创建一个目录:
>>> os.mkdir('/Users/michael/testdir')
# 删掉一个目录:
>>> os.rmdir('/Users/michael/testdir')

# 两个路径合成一个,通过os.path.join()函数,这样可以正确处理不同操作系统的路径分隔符
os.path.join('/Users/michael', 'testdir')
>>> os.path.join('/Users/michael', 'testdir')
# 拆分路径要用os.path.split(),可以把路径拆成两部分,后一部分是最后级别的目录或文件名
os.path.split('/Users/michael/testdir/file.txt')
>>> ('/Users/michael/testdir', 'file.txt')
# os.path.splitext() 拆分文件后缀名
os.path.splitext('path/to/file.txt')
>>> ('/path/to/file', '.txt')
# 这些合并/拆分操作并不要求目录文件真实存在,只是字符串操作

# 重命名和删除
os.rename('test.txt', 'test.py')
os.remove('test.py')

复制文件的函数在os模块中并不存在,原因是复制文件并不是由系统提供的系统调用.shutil模块提供了copyfile()函数来实现.

shutil可以看作是os的补充

两个例子

1
2
3
4
# 列出当前目录下所有文件夹
[x for x in os.listdir('.') if os.path.isdir(x)]
# 列出当前目录下所有.py文件
[x for x in os.listdir('.') if ps.path.isfile(x) and os.path.splitext(x)[1]=='.py']

序列化

变量从内存中变为可存储或传输的过程称为序列化.

python中叫pickling,其他语言有不同的称呼,都是一个意思.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# python提供pickle模块来实现序列化
import pickle
d = dict(name='Bob', age=20, score=88)
pickle.dump(d) # 把任意对象序列化成一个bytes,然后就可以把这个bytes写入文件

# 也可以直接写入一个file-like object
f = open('dump.txt', 'wb')
pickle.dump(d, f)
f.close()
# 如果直接查看写入的dump.txt文件,你会发现是一堆乱七八糟的内容,这些都是python保存的对象内部信息

# 如果要把对象从磁盘读到内存,可以先把内容读取到一个bytes,然后用pickle.loads()方法反序列化出对象,也可以直接用pickle.load()从一个file-like object中反序列化出对象
f = open('dump.txt', 'rb')
d = pickle.load(f)
f.close()
print(d)
>>> {name='Bob', age=20, score=88}
# 需要注意的是,反序列化出来的变量和原来的变量是完全不相干的两个对象

JSON

基础

如果我们要在不同的编程语言/程序之间传递对象,就必须把对象序列化为标准格式,业界通用做法就是JSON.它表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输,还可以直接在web页面中读取,非常方便.

json类型python类型
{}dict
[]list
“string”str
1234.56int或float
true/falsebool
nullNone

内置json模块常用方法

1
2
3
4
import json
d = dict(name='Bob', age=20, score=88)
json.dumps(d) # dumps()返回一个字符串,内容就是标准json
>>> '{"age": 20, "score": 88, "name": "Bob"}'
方法作用
dumps()返回一个字符串,内容就是标准json
dump()直接把python对象序列化成json并写入file-like object
loads()把json反序列化为python对象
load()直接从file-like object读取字符串并反序列化

JSON进阶

python的class 实例和json也可以序列化和反序列化

绝大部分python的class的实例都有__dict__属性,用于保存class的变量,序列化时可以直接调用,如果不用它则手动写一个转换函数,例如:

1
2
3
4
5
def student2dict(s):
return {
'name': s.name,
'age': s.age
}

反序列化时需要手动写一个转换函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import json

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

def dict2student(d):
return Student(d['name'], d['age'])

# 创建一个student实例
s = Student("张三", 20)

# 序列化,通过default指定转换函数
json_str = json.dumps(s, default=lambda obj:obj.__dict__) # 使用__dict__
json_str = json.dumps(s, default=student2dict) # 使用转换函数
# lambda 匿名函数
# obj: 匿名函数的传参
# obj.__dict__ 匿名函数的返回值
print('序列化结果:', json_str)
# 反序列化,通过object_hook指定转换函数
student_object = json.loads(json_str, object_hook=dict2student)
print('反序列化结果:', student_object.name, student_object.age)

pyhton笔记-IO编程
http://example.com/2024/08/22/pyhton-io/
作者
Peter Pan
发布于
2024年8月22日
许可协议