Python学习(六)

读写文件

  • 常规写法

      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>

你可能感兴趣的:(Python学习(六))