一. 读文件
读文件可以使用open()函数,传入文件名和标示符,标识符有以下几种:
open('文件名','r'):读取UTF-8编码的文本文件
open('文件名','rb'):读取二进制文件,比如图片、视频等
open('文件名', 'r', encoding='gbk'):读取GBK编码的文本文件
open('文件名', 'r', encoding='gbk', errors='ignore'):读取GBK编码的文本文件,并忽略错误编码
f = open('/Users/zhangjia/Desktop/test.txt','r') print(f.read()) f.close()
读完文件后必须调用close方法关闭文件,但是如果我们访问不存在的文件就可能触发IOError,除了可以通过try捕获外,Python还引入了with语句来自动帮我们调用close()方法
with open('/Users/zhangjia/Desktop/test.txt','r') as f: for line in f.readlines(): print(line.strip()) # line存储了数组内容,通过strip把末尾的'\n'删掉
open函数返回的对象可以调用以下几种用法:
-
read():一次性读取文件的全部内容
-
read(size):一次读取指定大小的文件内容
-
readlines():一次读取所有内容并按行返回list,适合读取配置文件
像open()函数返回的这种有个read()方法的对象,在Python中统称为file-like Object,file-like Object不要求从特定类继承,只要写个read()方法就行,StringIO就是在内存中创建的file-like Object,常用作临时缓冲。
二. 写文件
写文件和读文件是一样的,唯一区别是调用open()函数时,传入标识符'w'或者'wb'表示写文本文件或写二进制文件,以'w'模式写入文件时,如果文件已存在,会直接覆盖(相当于删掉后新写入一个文件)。通过传入'a'参数可以在文件末尾以追加(append)模式写入。
# with open('/Users/zhangjia/Desktop/test.txt','w') as f: with open('/Users/zhangjia/Desktop/test.txt','a') as f: f.write("123456")
三. StringIO和BytesIO
在内存中读写str:
>>> from io import StringIO >>> f = StringIO() >>> f.write('hello') 5 >>> f.write(' ') 1 >>> f.write('world!') 6 >>> print(f.getvalue()) hello world!
在内存中读写二进制数据:
>>> from io import BytesIO >>> f = BytesIO() >>> f.write('中文'.encode('utf-8')) 6 >>> print(f.getvalue()) b'\xe4\xb8\xad\xe6\x96\x87'
此外,要读取StringIO和BytesIO,还可以用一个str初始化,然后,像读文件一样读取
>>> from io import StringIO >>> f = StringIO('Hello!\nHi!\nGoodbye!') >>> from io import BytesIO >>> f = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')
四. 操作文件和目录
常见操作文件和目录的操作如下代码,注意,把两个路径合成一个时,不要直接拼字符串,而要通过os.path.join()函数,这样可以正确处理不同操作系统的路径分隔符,同理,要拆分路径时,也不要直接去拆字符串,而要通过os.path.split()函数
import os import shutil print(os.name) # 操作系统类型 print(os.uname) # 获取详细的系统信息 print(os.environ) # 操作系统中定义的环境变量 print(os.environ.get('PATH')) # 获取某个具体的环境变量的值 # 查看当前目录的绝对路径: print(os.path.abspath('.')) # /Users/zhangjia/Personal/Python/Projects/Test # 在某个目录下创建一个新目录,首先把新目录的完整路径表示出来: print(os.path.join('/Users/zhangjia/Desktop', 'newDir')) # 然后用上面的输出,创建一个目录: os.mkdir('/Users/zhangjia/Desktop/newDir') # 删掉一个目录: os.rmdir('/Users/zhangjia/Desktop/newDir') # 获取扩展名 os.path.splitext('/Users/zhangjia/Desktop/text.txt') # 重命名文件 os.rename('/Users/zhangjia/Desktop/text.txt', '/Users/zhangjia/Desktop/text2.txt') # 删除文件 os.remove('/Users/zhangjia/Desktop/text2.txt') # 新建文件 with open('/Users/zhangjia/Desktop/text3.txt','w') as f: f.write(123) # 复制文件 shutil.copy('/Users/zhangjia/Desktop/text3.txt','/Users/zhangjia/Desktop/text4.txt')
要列出当前目录下的所有目录,只需要一行代码:
import os print([x for x in os.listdir('.') if os.path.isdir(x)])
要列出所有的.py文件,也只需一行代码
import os [x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py']
五. 序列化
我们把变量从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。Python提供了pickle模块来实现序列化。
方法一:pickle.dumps()方法把任意对象序列化成一个bytes,然后,就可以把这个bytes写入文件
import pickle d = dict(name='Jia', age=20, score=88) print(pickle.dumps(d))
方法二:pickle.dump()直接把对象序列化后写入一个file-like Object
import pickle f = open('dump.txt', 'wb') d = dict(name='Bob', age=20, score=88) pickle.dump(d, f) f.close()
当我们要把对象从磁盘读到内存时,可以先把内容读到一个bytes,然后用pickle.loads()方法反序列化出对象
import pickle d = pickle.loads(b'\x80\x04\x95$\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x04name\x94\x8c\x03Jia\x94\x8c\x03age\x94K\x14\x8c\x05score\x94KXu.') print(d)
也可以直接用pickle.load()方法从一个file-like Object中直接反序列化出对象。
import pickle f = open('dump.txt', 'rb') d = pickle.load(f) f.close() print(d)
但Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据
六. JSON
JSON和Python内置的数据类型对应如下:
把Python对象转换成JSON:
import json d = dict(name='Jia', age=20, score=88) print(json.dumps(d))
dump()方法可以直接把JSON写入一个file-like Object
把JSON转换为Python对象:
import json json_str = '{"age": 20, "score": 88, "name": "Jia"}' print(json.loads(json_str))
七. 序列化自定义类
自定义序列化类是没法直接序列化的,需要写def student2dict(std)转换函数,也可以直接通过传参的方式转换:
import json class Student(object): def __init__(self, name, age, score): self.name = name self.age = age self.score = score def student2dict(std): return { 'name': std.name, 'age': std.age, 'score': std.score } s = Student('Jia', 20, 88) # print(json.dumps(s)) #TypeError print(json.dumps(s, default=lambda obj: obj.__dict__))
同样的道理,如果我们要把JSON反序列化为一个Student对象实例,loads()方法首先转换出一个dict对象,然后,我们传入的object_hook函数负责把dict转换为Student实例:
import json class Student(object): def __init__(self, name, age, score): self.name = name self.age = age self.score = score def dict2student(d): return Student(d['name'], d['age'], d['score']) j = '{"name": "Jia", "age": 20, "score": 88}' print(json.loads(j)) #{'name': 'Jia', 'age': 20, 'score': 88} print(json.loads(j,object_hook=dict2student)) #<__main__.Student object at 0x7fbb000a8250>
请登录之后再进行评论