ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

9、Python基础之IO编程

9、Python基础之IO编程

前言

IO就是Input/Output,输入输出。程序和外部数据交换都属于IO操作:读取文件、写入文件、网络传输等。IO操作有一个核心特点:速度远慢于CPU计算。 Python内置了丰富的IO支持,本篇包含:文件读写、StringIO/BytesIO、文件目录操作、序列化。

文件读写

文件读写是最常见的IO。遵循流程:打开文件 → 读写内容 → 关闭文件。

open()基础用法

# 读取文本文件 f = open("test.txt", "r", encoding="utf-8") content = f.read() print(content) f.close()
  • "r":读文本模式;"w":写文本(覆盖原有内容);"a":追加写入
  • encoding="utf-8":指定文件编码,一定要显式指定,防止乱码
  • read():一次性读取全部内容;大文件不要直接read(),容易撑爆内存

风险:如果中间代码抛出异常,close()不会执行,文件句柄泄漏。推荐使用with上下文管理器,自动关闭文件。

# with语句(推荐),退出代码块自动close with open("test.txt", "r", encoding="utf-8") as f: print(f.read())

按行读取、分块读取

# readline() 读一行 with open("test.txt", "r", encoding="utf-8") as f: line = f.readline() print(line) # readlines() 读取所有行,返回列表 with open("test.txt", "r", encoding="utf-8") as f: lines = f.readlines() # 直接迭代文件对象(最省内存) with open("test.txt", "r", encoding="utf-8") as f: for line in f: print(line.strip())

二进制读写

图片、视频、音频都是二进制文件,用rb / wb

# 读取图片 with open("demo.jpg", "rb") as f: data = f.read()

写文件

# w模式:覆盖原文件 with open("out.txt", "w", encoding="utf-8") as f: f.write("Hello IO\n") # a模式:追加,不会覆盖 with open("out.txt", "a", encoding="utf-8") as f: f.write("追加一行\n")

StringIO 和 BytesIO

有时候数据不需要落地到磁盘文件,只在内存中读写,就用这两个工具,在内存里模拟文件。

StringIO:内存读写字符串

from io import StringIO # 写入 f = StringIO() f.write("hello") f.write(" python") print(f.getvalue()) # 获取全部字符串 # 读取 f2 = StringIO("你好\nPython") while True: line = f2.readline() if not line: break print(line.strip())

BytesIO:内存读写bytes字节数据

用于二进制,比如图片字节、网络二进制流

from io import BytesIO f = BytesIO() f.write("中文".encode("utf-8")) print(f.getvalue()) # 读取 data = b'\xe4\xb8\xad\xe6\x96\x87' f2 = BytesIO(data) print(f2.read())

区别:StringIO操作str;BytesIO操作bytes。

操作文件和目录

Python内置os模块,调用操作系统接口,实现目录创建、删除、遍历、路径拼接。

注意:os模块的函数很多和操作系统强相关,Windows和Linux路径格式不一样,不要手动拼接字符串,使用os.path

import os # 当前工作目录 print(os.getcwd()) # 列出指定目录下所有文件和子目录 print(os.listdir(".")) # 判断是否是目录 print(os.path.isdir("./test")) # 判断是否是文件 print(os.path.isfile("test.txt")) # 路径拼接(跨平台兼容) p = os.path.join(".", "data", "test.txt") print(p) # 创建文件夹 # os.mkdir("./demo") # 删除文件夹 # os.rmdir("./demo") # 删除文件 # os.remove("a.txt")

遍历目录下所有文件(常用)

import os def scan_dir(path): for name in os.listdir(path): full_path = os.path.join(path, name) if os.path.isdir(full_path): scan_dir(full_path) else: print(full_path) # scan_dir(".")

补充:Python3.4+ 推荐 pathlib,面向对象路径写法,但廖雪峰教程主线用os。

序列化

把内存中的变量(dict、list、对象)变成可以存储/传输的字节或者字符串,叫序列化;反向恢复成内存变量叫反序列化。 Python标准库pickle和json。

pickle:Python专用序列化

可以序列化绝大多数Python对象,但是只能给Python程序读取,跨语言不行。

import pickle d = {"name": "小明", "age": 18} # 序列化到bytes b = pickle.dumps(d) print(b) # 反序列化 res = pickle.loads(b) print(res) # 序列化写入文件 with open("dump.pkl", "wb") as f: pickle.dump(d, f) # 从文件读取 with open("dump.pkl", "rb") as f: d2 = pickle.load(f)

json:通用JSON序列化(工程最常用)

JSON是跨语言通用格式,只能序列化基础类型:dict、list、str、int、float、bool、None,不能直接序列化自定义类实例。

import json d = {"name": "小明", "age": 18} # dict -> json字符串 s = json.dumps(d, ensure_ascii=False, indent=2) print(s) # json字符串 -> dict d2 = json.loads(s) print(d2) # 写入文件 with open("data.json", "w", encoding="utf-8") as f: json.dump(d, f, ensure_ascii=False, indent=2) # 读取文件 with open("data.json", "r", encoding="utf-8") as f: d3 = json.load(f)

参数说明:

  • ensure_ascii=False:中文正常显示,不会转\u编码
  • indent=2:格式化缩进,方便阅读

如果要序列化自定义类对象,需要自己写转换函数,把对象转成dict再dumps。

小结

  1. 文件读写:优先with open()自动关闭,区分文本模式r/w/a和二进制rb/wb,指定utf-8编码;
  2. StringIO / BytesIO:内存文件,不需要磁盘IO,处理临时字符串、二进制流;
  3. os模块:操作系统目录、文件,os.path.join跨平台拼接路径;
  4. 序列化:pickle(Python专属),json(跨语言通用,业务首选)。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进