通常,程序完成 IO 操作会有 Input 和 Output 两个数据流。Input Stream 就是数据从外面(磁盘、网络)流进内存, Output Stream 就是数据从内存流到外面去。
分类:同步IO、异步IO。区别就在于是否等待 IO 执行的结果。
异步 IO 来编写程序性能会远远高于同步 IO,但是异步 IO
的缺点是编程模型复杂。
读写文件:请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。
步骤:open()、read()、close()
open() 函数传入文件名和标示符。其中,r 表示只读。
f = open('E:\codes\python\basic\1.py', 'r')
==》若文件不存在,则抛出 IOError 错误。
调用 read() 方法可一次读取文件的全部内容到内存中,用一个 str 对象表示。
f.read()
关闭文件——close() 方法
==》文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的。
f.close()
避免产生IOError的错误,而导致后面close()无法调用。
try:
f = open('E:\\codes\\python\\basic\\1.txt', 'r')
print(f.read())
finally:
if f:
f.close()
简洁、不用 f.close() 方法
with open('E:\\codes\\python\\basic\\1.txt', 'r') as f:
print(f.read())
二进制文件:图片、视频等等==》‘rb’模式打开文件
f = open('/Users/michael/test.jpg', 'rb')
f.read()
# b'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...' # 十六进制表示的字节
读取 GBK 编码的文件。==》encoding = ‘gbk’
当遇到 UnicodeDecodeError (文件中夹杂一些非法编码的字符)==》errors = ‘ignore’,也就是忽略编码错误。
f = open('/Users/michael/gbk.txt', 'r', encoding='gbk', errors='ignore')
open() 函数,标示符为 ‘w’ 或 ‘wb’,表示写文本文件或写二进制文件。
f = open('/Users/michael/test.txt', 'w')
f.write('Hello, world!')
f.close()
注意:写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。只有调用 close()方法时,操作系统才保证把没有写入的数据全部写入磁盘。
可以使用 encoding 参数设置指定的编码。
with open('/Users/michael/test.txt', 'w') as f:
f.write('Hello, world!')
表示在内存中读写 str。
from io import StringIO
#### 写入
f = StringIO()
print(f.write('hello'))
print(f.write(' '))
print(f.write('world!'))
# getvalue(): 获得写入后的 str
print(f.getvalue())
#### 读取
f = StringIO('Hello!\nHi!\nGoodbye!')
while True:
s = f.readline()
if s == '':
break
print(s.strip())
输出结果
5
1
6
hello world!
Hello!
Hi!
Goodbye!
表示在内存中读写 二进制数据。
from io import BytesIO
### 写入
f = BytesIO()
print(f.write('中文'.encode('utf-8')))
print(f.getvalue())
### 读取
f = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')
print(f.read())
输出结果
6
b'\xe4\xb8\xad\xe6\x96\x87'
b'\xe4\xb8\xad\xe6\x96\x87'
模块:os
注意:os 模块的某些函数是跟操作系统相关的
import os
print(os.name) # 操作系统类型
# uname()在 Linux 有,Windows 没有
# print(os.uname()) # 获取详细的系统信息
print(os.environ) # 环境变量
print(os.environ.get('PATH')) # 获取某个环境变量的值
在 os 模块 和 os.path 模块中 + shutil 模块
print(os.path.abspath('.')) # 查看当前目录的绝对路径
# 在某个目录下创建一个新目录,首先把新目录的完整路径表示出来
print(os.path.join('E:\codes\python\\basic', 'testdir'))
## 创建一个目录
os.mkdir('E:\codes\python\\basic\\1')
## 删除一个目录
os.rmdir('E:\codes\python\\basic\\1')
# 对文件重命名:
os.rename('test.txt', 'test.py')
# 删掉文件:
os.remove('test.py')
# 复制文件
from shutil import copyfile
copyfile('1.py', '11.py') # 源文件 ==》 目标文件
把两个路径合成一个时,不要直接拼字符串。==》os.path.join() 函数,可以正确处理不同操作系统的路径分隔符。
同理,要拆分路径时==》os.path.split()函数,后一级别总是目录或文件名。
拆分扩展名——os.path.splitext() 函数
过滤文件
## 列出所有的.py 文件
print([x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1] == '.py'])
序列化:把变量从内存中变成可存储或传输的过程。在Python中称为 picking。
反序列化:把变量内容从序列化的对象重新读到内存里的过程。在Python中称为 unpicking。
把一个对象序列化并写入文件。
import pickle
d = dict(name = 'Bob', age = 20, score = 88)
pickle.dumps(d)
# b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x03\x00\x00\x00Bobq\x02X\x03\x00\x00\x00ageq\x03K\x14X\x05\x00\x00\x00scoreq\x04KXu.'
## 序列化到dump.txt文件中
f = open('dump.txt', 'wb')
pickle.dump(d, f)
f.close()
## 反序列化
f = open('dump.txt', 'rb')
d = pickle.load(f)
f.close()
print(d)
pickle.dumps() 方法:把任意对象序列化成一个bytes,然后就可以把这个 bytes 写入文件。
pickle.dump() 方法:直接把对象序列化后写入一个 file-like Object.
把对象从磁盘读取到内存时。
(1)内容=》bytes=》pickle.loads() 方法反序列化出对象
(2)直接用 pickle.load() 从一个file-like Object 中直接反序列化出对象。
注意:Python不同版本的Pickle可能不兼容,所以只能保存那些不重要的数据,不能成功反序列化也没关系。
序列化的标准化格式:JSON,且比XML快,可以在Web网页中读取。
JSON 与 Python的内置数据类型对应如下:
JSON类型 | Python类型 |
---|---|
{} | dict |
[] | list |
“string” | str |
1234.56 | int 或 float |
true/false | True/False |
null | None |
dict 《==》dict
import json
d = dict(name = 'Bob', age = 20, score = 88)
print(json.dumps(d))
json_str = '{"age":20, "score":88, "name":"Bob"}'
print(json.loads(json_str))
import json
class Student(object):
def __init__(self, name, age, score):
self.name = name
self.age = age
self.score = score
## 序列化——default参数
s = Student('Bob', 20, 88)
# obj.__dict__:把任意 class 的实例变为 dict
print(json.dumps(s, default=lambda obj: obj.__dict__))
## 反序列化
def dict2student(d):
return Student(d['name'], d['age'], d['score'])
json_str = '{"age":20, "score":88, "name":"Bob"}'
print(json.loads(json_str, object_hook=dict2student))