文件读写
读文件:open()、read()、close()。对于文件的操作一般都放在try ... except ... finally
一段完整的文件读取代码:
try: f = open(‘/path/to/file‘, ‘r‘) print(f.read()) finally: if f: f.close()
简写:
with open(‘/path/to/file‘, ‘r‘) as f: print(f.read())
简写的好处是:简洁,且不必调用close()方法。
read()一次读取全部内容,防止文件太大内存溢出,可以反复调用read(size)方法,每次最多读取size个字节内容。readline()一次读一行,readlines()一次读取所有内容并按行返回list。
open()返回的有个read()的对象,叫做file-like object。还可以是字节流,网络流,自定义流。它不要求从特定类继承,只要写个read()方法就成。
打开二进制文件需要一个b模式。
f = open(‘/path/to/file‘, ‘rb‘) f.read()
读取非utf8的文本,需要给open()传入encoding参数。
f = open(‘/path/to/file‘, ‘r‘, encoding=‘gbk‘ f.read()
编码不规范的文件,open()函数可使用errors参数,遇到编码错误的处理一般是忽略
f = open(‘/path/to/file‘, ‘r‘, encoding=‘gbk‘, errors=ignore‘)
写文件:open()、write()、close()。和读文件一样。调用open()时,使用‘w‘或‘wb‘。
f = open(‘/path/to/file‘, ‘w‘) f.write("hello, world") f.close()
方式写文件的数据丢失,使用with语句:
with open(‘/path/to/file‘, ‘w‘) as f: f.write(‘hello, world‘)
写特殊编码的文件,使用open()函数传入encoding参数。
写内存流的时候使用StringIO和BytesIO
str写入StringIO,需要创建一个StringIO,然后写入。
from io import StringIO f = StringIO() f.write(‘hello world!‘) print(f.getvalue()) hello world!
getvalue()获得写入后的str。
读取StringIO的内容
from io import StringIO f = StringIO(‘hello\nHi\ngoodbye!) while True: s = f.readline() if s == ‘‘: break print(s.strip()) hello Hi goodbye!
二进制的操作使用BytesIO
from io import BytesIO f = BytesIO() f.write(‘中文‘.encode(‘utf-8‘)) print(f.getvalue()) b‘\xe4\xb8\xad\xe6\x96\x87‘
读操作同StringIO()
文件和目录的操作
使用os和os.path模块。
os.name
os.uname()
os.environ
os.environ.get(‘PATH‘)
os.path.abspath(‘.‘)
把一个目录加入另一个目录
os.path.join(‘/path/to‘, ‘test‘)把test加入到to中
os.mkdir(‘/path/to/test‘)创建一个目录
os.rmdir(‘/path/to/test‘)删除一个目录
os.path.split(‘/path/to/test/test.txt‘)拆分一个文件的路径为绝对路径和一个文件名。
(‘/path/to/test‘, ‘test.txt‘)
os.path.splitext(‘/path/to/test.txt‘)
(‘/path/to/test‘, ‘.txt‘)
上面这些操作不要求目录或文件存在,只是对字符串的操作。
os.rename(‘test.txt‘, ‘test.py‘)文件改名
os.remove(‘test.py‘)删除文件
shutil模块提供了文件复制的函数copyfile()
序列化 -- pickling 反序列化 -- unpickling
其他语言称为 serialization,marshalling,flattening
序列化:就是把变量从内存中变成可存储或传输的过程。序列化之后可以把序列化后的内容写入磁盘,或传输。
反序列化:把变量内容从序列化的对象重新读到内存里。
序列化和反序列化实例:
import pickle d = dict(name=‘bart‘, age=20, score=88) pickle.dumps(d) 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‘:‘bart‘}
Json的操作 -- python中json比xml更快。
import json d = dict(name=‘bart‘, age=20, score=88) json.dumps(d) json_str = ‘{"age":20, "score":88, "name":"bart"}‘ json.loads(json_str) {"age":20, "score":88, "name":"bart"}
把一个对象序列化为一个json
import json class Student(object): def __init__(self, name, age, score): self.name = name self.age = age self.score = score s = Student(‘bart‘, 20, 88) # print(json.dumps(s)) typeerror # 使用dumps的可选参数defalut把任意一个对象变成一个可序列化为json的对象。需要一个函数来转换。 def student2dict(std): return { ‘name‘: std.name, ‘age‘: std.age, ‘score‘: std.score } print(json.dumps(s, default=student2dict)) {"age":20, "name":bart, "score":88} # 把任意class变为dict: print(json.dumps(s, default=lamba obj:obj.__dict__)) # class的实例都有一个__dict__属性。除了__slots__的class # 要把Json反序列化一个Student对象实例,loads()首先转换出一个dict对象,然后传入的object_hook函数负责把dict转换为Student实例: def dict2student(d): return Student(d[‘name‘], d[‘age‘], d[‘score‘]) json_str = ‘{"age":20, "name": "bart", "score":88}‘ print(json.loads(json_str, object_hook=dict2student)) <__main__.Student object at 0x10cd3c190>