Python中的`io`模块

Python中的`io`模块

本文介绍了Python中的io模块。

我们将用实际例子解释Python中的io模块。

YouTube Video

Python中的io模块

输入/输出处理构成了各种数据操作的基础,例如文件、网络和标准I/O。Python的io模块提供了一套抽象类,统一了这些输入/输出操作。理解该模块的关键概念是“流”的思想。

什么是流?

流是一种用于顺序和连续读写数据的抽象数据流。

当逐字节读取文件内容或通过网络发送和接收数据时,这些都可以作为数据流来处理。

通过对这一机制进行抽象,文件、内存和网络等不同的I/O来源都可以通过通用的读写等操作来处理。

Python的io模块为流提供了统一的接口,可高效处理文本和二进制数据。

io模块的基本结构

io模块根据流的性质分为三层结构。

  1. 原始层(RawIOBase

    RawIOBase处理最低层的字节I/O,如操作系统文件描述符和设备。

  2. 缓冲层(BufferedIOBase

    BufferedIOBase提供缓存(缓冲区)以提升I/O效率。BufferedReaderBufferedWriter是典型示例。

  3. 文本层(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的抽象类集合。你可以看到TextIOBaseBufferedIOBaseRawIOBase,确认它们的分层结构。

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()
  • FileIORawIOBase的一个具体实现,所有的读写以bytes的方式进行。与上层的BufferedIOBase结合可提高效率。

io.BufferedIOBase:中间缓冲层

BufferedIOBase是实现缓冲处理的中间层,使磁盘访问更高效。主要实现包括BufferedReaderBufferedWriterBufferedRandomBufferedRWPair

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是管理字符串读写的类。
  • StringIOBytesIO是提供内存流的类。

理解这些类能让你准确把握Python I/O系统的工作原理,并可以将其应用于文件操作、网络通信和测试流的设计。

您可以在我们的YouTube频道上使用Visual Studio Code跟随上述文章进行学习。 请也查看我们的YouTube频道。

YouTube Video