Python中的`io`模块
本文介绍了Python中的io模块。
我们将用实际例子解释Python中的io模块。
YouTube Video
Python中的io模块
输入/输出处理构成了各种数据操作的基础,例如文件、网络和标准I/O。Python的io模块提供了一套抽象类,统一了这些输入/输出操作。理解该模块的关键概念是“流”的思想。
什么是流?
流是一种用于顺序和连续读写数据的抽象数据流。
当逐字节读取文件内容或通过网络发送和接收数据时,这些都可以作为数据流来处理。
通过对这一机制进行抽象,文件、内存和网络等不同的I/O来源都可以通过通用的读写等操作来处理。
Python的io模块为流提供了统一的接口,可高效处理文本和二进制数据。
io模块的基本结构
io模块根据流的性质分为三层结构。
-
原始层(
RawIOBase)RawIOBase处理最低层的字节I/O,如操作系统文件描述符和设备。 -
缓冲层(
BufferedIOBase)BufferedIOBase提供缓存(缓冲区)以提升I/O效率。BufferedReader和BufferedWriter是典型示例。 -
文本层(
TextIOBase)TextIOBase将字节序列转换为字符串,并处理编码。通常,在用open()函数打开文件时,会使用该层的TextIOWrapper。
得益于这种结构,io模块能够清晰地区分文本和二进制I/O,并允许灵活组合使用。
io模块的基本结构
RawIOBase在最低层处理操作系统文件描述符,BufferedIOBase在其上层添加缓存,最上层的TextIOBase负责字符串转换。
1import io
2
3# Check the core base classes hierarchy
4print(io.IOBase.__subclasses__())- 这段代码用于检查继承自
IOBase的抽象类集合。你可以看到TextIOBase、BufferedIOBase和RawIOBase,确认它们的分层结构。
io.IOBase:所有流的基类
IOBase是所有I/O对象的抽象基类,定义了如close()、flush()和seekable()等通用方法。它很少被直接使用,通常通过派生类进行访问。
1import io
2
3f = io.StringIO("data")
4print(f.seekable()) # True
5print(f.readable()) # True
6print(f.writable()) # True
7f.close()- 该示例表明
IOBase的通用方法也可在上层类中使用。seekable()和readable()用于检查流的属性,非常实用。
io.RawIOBase:最低层
RawIOBase是最接近操作系统文件描述符的层,不进行缓存。典型实现为FileIO,它按字节进行读写操作。
1import io, os
2
3# Create a low-level FileIO object (no buffering)
4fd = os.open('raw_demo.bin', os.O_RDWR | os.O_CREAT)
5raw = io.FileIO(fd, mode='w+')
6raw.write(b'abc123')
7raw.seek(0)
8print(raw.read(6)) # b'abc123'
9raw.close()FileIO是RawIOBase的一个具体实现,所有的读写以bytes的方式进行。与上层的BufferedIOBase结合可提高效率。
io.BufferedIOBase:中间缓冲层
BufferedIOBase是实现缓冲处理的中间层,使磁盘访问更高效。主要实现包括BufferedReader、BufferedWriter、BufferedRandom和BufferedRWPair。
1import io
2
3# Create a buffered binary stream on top of a BytesIO (simulate file)
4base = io.BytesIO()
5buffered = io.BufferedWriter(base)
6buffered.write(b'Python IO buffering')
7buffered.flush()
8base.seek(0)
9print(base.read()) # b'Python IO buffering'- 在此示例中,通过
BufferedWriter写入的数据会临时存储在内存缓冲区,只有调用flush()时才真正传递到下层。
BufferedReader示例
BufferedReader 是一个只读的缓冲流,支持使用 peek() 和 read() 进行高效读取。
1import io
2
3stream = io.BytesIO(b"1234567890")
4reader = io.BufferedReader(stream)
5print(reader.peek(5)) # b'12345' (non-destructive)
6print(reader.read(4)) # b'1234'
7print(reader.read(3)) # b'567'peek()只“窥视”数据,并不会移动指针。与read()结合使用,可以灵活地控制缓冲。
io.TextIOBase:仅文本层
TextIOBase 是处理字符串的抽象层,内部执行解码和编码。典型的实现类是TextIOWrapper。
1import io
2
3# Wrap a binary stream to handle text encoding
4binary = io.BytesIO()
5text_stream = io.TextIOWrapper(binary, encoding='utf-8')
6text_stream.write("\u3053\u3093\u306B\u3061\u306F")
7text_stream.flush()
8
9# Reset stream position
10binary.seek(0)
11
12# Read bytes once
13data = binary.read()
14
15# Show both raw bytes and decoded text
16print("Raw bytes:", data)
17print("Decoded text:", data.decode('utf-8'))- 在此示例中,
TextIOWrapper将字符串编码为UTF-8并写入底层二进制流。
TextIOWrapper读取示例
读取时会自动完成解码。
1import io
2
3binary_data = io.BytesIO("Python I/O".encode('utf-8'))
4text_reader = io.TextIOWrapper(binary_data, encoding='utf-8')
5print(text_reader.read()) # 'Python I/O'TextIOWrapper是文本I/O的基础类,几乎所有高级文件操作都基于此类。
io.StringIO:内存中文本流
StringIO是一个可以在内存中像操作文件一样处理字符串的类。它适用于I/O测试和临时数据生成。
1import io
2
3text_buf = io.StringIO()
4text_buf.write("In-memory text stream")
5text_buf.seek(0)
6print(text_buf.read()) # 'In-memory text stream'StringIO无需使用磁盘即可进行类文件操作,被广泛用于单元测试。
io.BytesIO:内存中二进制流
BytesIO是在内存中处理字节序列(bytes)的文件类。在不希望使用文件的场景下,如二进制处理或数据压缩等,BytesIO非常有用。
1import io
2
3buf = io.BytesIO()
4buf.write(b'\x01\x02\x03')
5buf.seek(0)
6print(list(buf.read())) # [1, 2, 3]BytesIO拥有与BufferedIOBase相同的接口,可作为许多文件API的替代品。
自定义流(创建自定义类)
io模块中的类都是可扩展的,允许你创建自己的流类。下面是一个自TextIOBase派生的子类示例,它会将所有写入的文本转换为大写。
1import io
2
3class UpperTextIO(io.TextIOBase):
4 def __init__(self):
5 self.buffer = ""
6 def write(self, s):
7 self.buffer += s.upper()
8 return len(s)
9
10u = UpperTextIO()
11u.write("hello io")
12print(u.buffer) # "HELLO IO"- 只要遵循
TextIOBase的约定,你就可以像这样定义任何自定义行为。对于文件、网络等特定用途,扩展流类也很容易。
总结
io模块将输入/输出处理组织为抽象类和具体类的层次结构。
RawIOBase是处理操作系统级别字节I/O的类。BufferedIOBase是提供高效缓存层的类。TextIOBase是管理字符串读写的类。StringIO和BytesIO是提供内存流的类。
理解这些类能让你准确把握Python I/O系统的工作原理,并可以将其应用于文件操作、网络通信和测试流的设计。
您可以在我们的YouTube频道上使用Visual Studio Code跟随上述文章进行学习。 请也查看我们的YouTube频道。