IO编程
本章主要讲同步IO,异步IO太复杂,后续涉及到服务端再讲.
文件读写
读文件
open()
函数, f.close()
关闭文件;
调用read()
会一次性读取文件的全部内容, read(size)
读取size
个字符/字节的内容.
readline()
可以每次读取一行内容,调用readlines()
一次读取所有内容并按行返回list
>>> with open('ABC.txt', 'r') as fname :
>>> str = fname.read()
>>> f = open('/Users/michael/test.jpg', 'rb') #以二进制打开, 打开文本可以用decode解码为字符串
>>> f.read()
b'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...' # 十六进制表示的字节
for line in f.readlines():
print(line.strip()) # strip参数为空,把末尾的'\n'或空格删掉
写文件
调用open()
函数时,传入标识符'w'
或者'wb'
表示写文本文件或写二进制文件:新建或删除存在的内容.
追加内容用标识符:a
.
StringIO和BytesIO
tell
方法获取当前文件读取指针的位置seek
方法,用于移动文件读写指针到指定位置,有两个参数,第一个offset: 偏移量,需要向前或向后的字节数,正为向后,负为向前;第二个whence: 可选值,默认为0
,表示文件开头,1
表示相对于当前的位置,2
表示文件末尾- 用
seek
方法时,需注意,如果你打开的文件没有用'b'
的方式打开,则offset
无法使用负值哦
# stringIO 比如说,这时候,你需要对获取到的数据进行操作,但是你并不想把数据写到本地硬盘上,这时候你就可以用stringIO
from io import StringIO
from io import BytesIO
def outputstring():
return 'string \nfrom \noutputstring \nfunction'
s = outputstring()
# 将函数返回的数据在内存中读
sio = StringIO(s)
# 可以用StringIO本身的方法
print(sio.getvalue())
# 也可以用file-like object的方法
s = sio.readlines()
for i in s:
print(i.strip())
# 将函数返回的数据在内存中写
sio = StringIO()
sio.write(s)
# 可以用StringIO本身的方法查看
s=sio.getvalue()
print(s)
# 如果你用file-like object的方法查看的时候,你会发现数据为空
sio = StringIO()
sio.write(s)
for i in sio.readlines():
print(i.strip())
# 这时候我们需要修改下文件的指针位置
# 我们发现可以打印出内容了
sio = StringIO()
sio.write(s)
sio.seek(0,0)
print(sio.tell())
for i in sio.readlines():
print(i.strip())
# 上面涉及到了两个方法seek 和 tell
# stringIO 只能操作str,如果要操作二进制数据,就需要用到BytesIO
# 上面的sio无法用seek从当前位置向前移动,这时候,我们用'b'的方式写入数据,就可以向前移动了
bio = BytesIO()
bio.write(s.encode('utf-8'))
print(bio.getvalue())
bio.seek(-36,1)
print(bio.tell())
for i in bio.readlines():
print(i.strip())
操作文件与目录
os.chdir(file_path)
进入file_path路径;
os.path.abspath('.')
当前位置的绝对路径
os.path.join(pwd,x)
合并路径
os.listdir(pwd)
列出当前路径所有文件及目录(不包括子目录)
os.path.isfile(os.path.join(pwd,x))
判断括号内的路径是否为文件
os.path.isdir(os.path.join(pwd,x))
判断括号内的路径是否为目录
shutil
模块提供了copyfile()
的函数
>>> os.path.split('/Users/michael/testdir/file.txt')
('/Users/michael/testdir', 'file.txt')
>>> os.path.splitext('/path/to/file.txt') #获得文件拓展名
('/path/to/file', '.txt')
查找当前目录及子目录的指定文件名:
import os
def findfile(s, file_path):
#进入当前目录
os.chdir(file_path)
#查找当前目录包含输入字符串的文件
L = [x for x in os.listdir('.') if os.path.isfile(x)]
for x in L:
#查找是否包含s,包含返回开始s的下标,不包含返回-1
if x.find(s)!=-1:
print(os.path.join(file_path,x))
else:
pass
#查找各目录中是否包含输入字符串的文件
Y = [x for x in os.listdir('.') if os.path.isdir(x)]
for x in Y:
file_path2=os.path.join(file_path,x)
findfile(s,file_path2)
def main():
#path = input('请输入绝对路径:')
path = os.path.abspath('.')
s = input('请输入要查找的字符串:')
result = findfile(s, path)
if result == None :
print ('没找到或查找结束!')
if __name__ == '__main__':
main()
序列化
pickle
pickle.dumps()
方法把任意对象序列化成一个bytes
;
pickle.loads()
方法反序列化出对象;
pickle.dump()
直接把对象序列化后写入一个file-like Object
即写入文件;
pickle.load()
方法从一个file-like Object
中直接反序列化出对象.
>>> import pickle
>>> d = dict(name='Bob', age=20, score=88)
>>> pickle.dumps(d)
b'\x80\x03}q\x00(X\x03\x00\x00\x00ageq\x01K\x14X\x05\x00\x00\x00scoreq\x02KXX\x04\x00\x00\x00nameq\x03X\x03\x00\x00\x00Bobq\x04u.'
>>> f = open('dump.txt', 'wb')
>>> pickle.dump(d, f)
>>> f.close()
>>> f = open('dump.txt', 'rb')
>>> d = pickle.load(f)
>>> f.close()
>>> d
{'age': 20, 'score': 88, 'name': 'Bob'}
JSON
JSON类型 | Python类型 |
---|---|
{} | dict |
[] | list |
"string" | str |
1234.56 | int或float |
true/false | True/False |
null | None |
json
模块,dumps()
方法返回一个str
,内容就是标准的JSON
;类似的,dump()
方法可以直接把JSON
写入一个file-like Object
。
>>> import json
>>> d = dict(name='Bob', age=20, score=88)
>>> json.dumps(d)
'{"age": 20, "score": 88, "name": "Bob"}'
>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'
>>> json.loads(json_str)
{'age': 20, 'score': 88, 'name': 'Bob'}
class
转为json对象:
dumps()
方法的default
参数可以定义将class
转为dict
的函数;
import json
class Student(object):
def __init__(self, name, age, score):
self.name = name
self.age = age
self.score = score
s = Student('Bob', 20, 88)
def student2dict(std):
return {
'name': std.name,
'age': std.age,
'score': std.score
}
>>> print(json.dumps(s, default=student2dict))
{"age": 20, "name": "Bob", "score": 88}
通常class
的实例都有一个__dict__
属性,它就是一个dict
,用来存储实例变量; 少数例外,比如定义了__slots__
的class
。
print(json.dumps(s, default=lambda obj: obj.__dict__))
object_hook
函数负责把dict
转换为Student
实例:
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))
<__main__.Student object at 0x10cd3c190>