读写文件
-
常规写法
f = None try: # 标示符'r'表示读 f = open("./mysql.java", "r") # 一次性读取文件全部 print(f.read()) finally: if f: f.close()
-
简洁写法
with open("./mysql.java", "r") as i: # print(i.read()) # 如果不能确定文件大小,防止内存被爆,可反复调用read(size)方法,每次最多读取size个字节的内容 # print(i.read(6)) # 读取一行 readline() # print(i.readline()) # 调用readlines()一次读取所有内容并按行返回list,读取配置文件最方便 lines = i.readlines() print(lines) for line in lines: # 把末尾的'\n'删掉 strip用来删除首尾的空格 print(line.strip())
-
读二进制文件
-
读取二进制文件,比如图片、视频,用'rb'模式打开文件即可
with open("./down.jpg", "rb") as t: print(t.read()) # b'\xff\xd8\xff\xe0\... 十六进制表示的字节
-
open函数还可传入encoding参数,用来指定按什么编码来打开文件;open函数还可传入errors参数,表示如果遇到编码错误后如何处理。最简单的方式是直接忽略
with open("./gbk.txt", "r", encoding="gbk", errors="ignore") as g: print(g.read())
-
写文件
with open("./write.txt", "w") as w: w.write("Hello Python")
-
StringIO和BytesIO
StringIO在内存中读写str;BytesIO在内存中读写bytes
from io import StringIO, BytesIO
f = StringIO()
# 把str写入StringIO
r = f.write("Hello")
f.write(" ")
f.write("World!")
# 获取写入后的值
print(f.getvalue()) # Hello World!
s = StringIO("Hello\nPython")
while True:
line = s.readline()
if line == "":
break
print(line.strip()) # Hello \n Python
# 在内存中读写bytes
b = BytesIO()
# 将bytes写入BytesIO中
b.write("中文".encode("utf-8"))
print(b.getvalue()) # b'\xe4\xb8\xad\xe6\x96\x87'
# 读取BytesIO中的bytes
b2 = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')
print(b2.read()) # b'\xe4\xb8\xad\xe6\x96\x87'
操作文件和目录
import os
# 操作系统类型
print(os.name)
# 获取详细的系统信息
print(os.uname())
# 获取操作系统中定义的环境变量
print(os.environ)
# 查看当前目录的绝对路径
print(os.path.abspath(".")) # /Users/BlainPeng/Desktop/1/Python
# 通过join函数把把整个要创建的新目录的地址拼接出来
# os.path.join("../", "testDir")
# 然后创建这个目录
# os.mkdir("../testDir")
# 删除这个目录
# os.rmdir("../testDir")
# 拆分路径
print(os.path.split(os.path.abspath(".") + "/s1.py")) # ('/Users/BlainPeng/Desktop/1/Python', 's1.py')
# 获取文件扩展名
print(os.path.splitext(os.path.abspath(".") + "/s1.py")) # ('/Users/BlainPeng/Desktop/1/Python/s1', '.py')
# 给文件重新命名
# os.rename("test.txt", "test.py")
# 删掉文件
# os.remove("test.java")
# 列出当前目录下的所有目录
print(list(x for x in os.listdir(".") if os.path.isdir(x))) # ['.idea', 'q1']
# 列出当前目录下所有的.py文件
print(list(x for x in os.listdir(".") if os.path.isfile(x) and os.path.splitext(x)[1] == ".py")) # ['1.py', '2.py', '3.py', '4.py', '5.py', '6.py']
序列化(pickling)与反序列化(unpickling)
把变量从内存中变成可存储或传输的过程叫做序列化;反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化
import pickle
d = dict(name="Tom", age=18, score=90)
print(d) # {'score': 90, 'name': 'Tom', 'age': 18}
# 把任意对象序列化成一个bytes,接着就可以把这个bytes写入文件了
res = pickle.dumps(d)
print(res) # b'\x80\x03}q\x00(X\x05\x00\x00\x00scoreq...
# 将一个bytes反序列化成对象
src = pickle.loads(res)
print(src) # {'score': 90, 'name': 'Tom', 'age': 18}
# 把对象序列化后直接写入一个file-like object
f = open("dump.java", "wb")
pickle.dump(d, f)
f.close()
# 从一个file-like Object中直接反序列化出对象
r = open("dump.java", "rb")
print(pickle.load(r)) # {'score': 90, 'name': 'Tom', 'age': 18}
r.close()
此种序列化与反序列化只能用于Python,对于其它语言并不能兼容
Json
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输
import json
d2 = dict(姓名="Jim", 年龄=18, 分数=95)
# Python对象转化为JSON
res2 = json.dumps(d2, ensure_ascii=False)
print(res2) # {"分数": 95, "姓名": "Jim", "年龄": 18}
# 把JSON反序列化为Python对象
src2 = json.loads(res2)
print(type(src2)) #
print(src2) # {'分数': 95, '姓名': 'Jim', '年龄': 18}
with open("dump.json", "w", encoding="utf-8") as w:
# 直接把JSON写入一个file-like Object
json.dump(d2, w, ensure_ascii=False)
with open("dump.json", "r", encoding="utf-8") as r:
# 直接从file-like Object中读取字符串并反序列化
print(json.load(r)) # {'分数': 95, '姓名': 'Jim', '年龄': 18}
任意类转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
}
def dict2student(d):
return Student(d["name"], d["age"], d["score"])
s = Student("吉姆", 18, 50)
# 把任意一个类对象序列化成Json
# 可选参数default就是把任意一个对象变成一个可序列为JSON的对象,需要自己写转换函数
res = json.dumps(s, ensure_ascii=False, default=student2dict)
print(res) # {"name": "吉姆", "age": 18, "score": 50}
# 简单写法: 把任意类的实例变为dict
# 通常class的实例都有一个__dict__属性,它就是一个dict,用来存储实例变量。也有少数例外,比如定义了__slots__的class
print(json.dumps(s, ensure_ascii=False, default=lambda obj: obj.__dict__)) # {"score": 50, "name": "吉姆", "age": 18}
# 把Json转化成类对象
json_str = r'{"name": "Mary","age": 18,"score": 95}'
print(json.loads(json_str, object_hook=dict2student)) # <__main__.Student object at 0x101a95668>