f = open("myfile.txt", "r", encoding="utf-8")
内存中文本流也可以作为 StringIO
对象使用:
f = io.StringIO("some initial text data")
TextIOBase
的文档中详细描述了文本流的API
16.2.1.2. 二进制 I/O
二进制I/O(也称为缓冲I/O)预期 bytes-like objects 并产生 bytes
对象。不执行编码、解码或换行转换。这种类型的流可以用于所有类型的非文本数据,并且还可以在需要手动控制文本数据的处理时使用。
创建二进制流的最简单方法是使用 open()
,并在模式字符串中指定 'b'
:
f = open("myfile.jpg", "rb")
内存中二进制流也可以作为 BytesIO
对象使用:
f = io.BytesIO(b"some initial binary data: \x00\x01")
BufferedIOBase
的文档中详细描述了二进制流 API。
其他库模块可以提供额外的方式来创建文本或二进制流。参见 socket.socket.makefile()
的示例。
16.2.1.3. 原始 I/O
原始 I/O(也称为 非缓冲 I/O)通常用作二进制和文本流的低级构建块。用户代码直接操作原始流的用法非常罕见。不过,可以通过在禁用缓冲的情况下以二进制模式打开文件来创建原始流:
f = open("myfile.jpg", "rb", buffering=0)
The raw stream API is described in detail in the docs of RawIOBase
.
16.2.2. 高阶模块接口
io.
DEFAULT_BUFFER_SIZE
包含模块缓冲 I/O 类使用的默认缓冲区大小的 int。 在可能的情况下 open()
将使用文件的 blksize(由 os.stat()
获得)。
io.
open
(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
这是内置的 open()
函数的别名。
16.2.2.1. 内存中的流
也可以使用 str
或 bytes-like object 作为文件进行读取和写入。对于字符串, StringIO
可以像在文本模式下打开的文件一样使用。 BytesIO
可以像以二进制模式打开的文件一样使用。两者都提供完整的随机读写功能。
sys
包含标准IO流: sys.stdin
, sys.stdout
和 sys.stderr
。
I/O层次结构的顶部是抽象基类 IOBase
。它定义了流的基本接口。但是请注意,对流的读取和写入之间没有分隔。如果实现不支持指定的操作,则会引发 UnsupportedOperation
。
RawIOBase
ABC 是 IOBase
的子类。它负责将字节读取和写入流中。 RawIOBase
的子类 FileIO
提供计算机文件系统中文件的接口。
BufferedIOBase
ABC处理原始字节流 ( RawIOBase
) 上的缓冲。其子类 BufferedWriter
、BufferedReader
和 BufferedRWPair
缓冲流是可读、可写以及可读写的。 BufferedRandom
为随机访问流提供缓冲接口。 BufferedIOBase
的另一个子类 BytesIO
是内存中字节流。
TextIOBase
ABC是 IOBase
的另一个子类,它处理字节表示文本的流,并处理字符串之间的编码和解码。 TextIOWrapper
是其一个扩展,它是原始缓冲流( BufferedIOBase
)的缓冲文本接口。最后, StringIO
是一个用于文本的内存流。
参数名不是规范的一部分,只有 open()
的参数才用作关键字参数。
下表总结了抽象基类提供的 io
模块:
fileno
, seek
, 和 truncate
close
, closed
, __enter__
, __exit__
, flush
, isatty
, __iter__
, __next__
, readable
, readline
, readlines
, seekable
, tell
, writable
, 和 writelines
RawIOBase
IOBase
readinto
和 write
继承 IOBase
方法, read
, 和 readall
BufferedIOBase
IOBase
detach
, read
, read1
, 和 write
继承 IOBase
方法, readinto
, 和 readinto1
TextIOBase
IOBase
detach
, read
, readline
, 和 write
继承 IOBase
方法, encoding
, errors
, 和 newlines
class io.
IOBase
所有 I/O 类的抽象基类,作用于字节流。没有公共构造函数。
此类为许多方法提供了空的抽象实现,派生类可以有选择地重写。默认实现无法读取、写入或查找的文件。
Even though IOBase
does not declare read()
, readinto()
,
or write()
because their signatures will vary, implementations and
clients should consider those methods part of the interface. Also,
implementations may raise a ValueError
(or UnsupportedOperation
)
when operations they do not support are called.
The basic type used for binary data read from or written to a file is
bytes
. Other bytes-like objects are
accepted as method arguments too. In some cases, such as
readinto()
, a writable object such as bytearray
is required. Text I/O classes work with str
data.
请注意,在关闭的流上调用任何方法(甚至查询)都是未定义的(undefined)。在这种情况下,实现可能会引发 ValueError
。
IOBase
(及其子类)支持迭代器协议,这意味着可以迭代 IOBase
对象以产生流中的行。根据流是二进制流(产生字节)还是文本流(产生字符串),行的定义略有不同。请参见下面的 readline()
。
IOBase
is also a context manager and therefore supports the
with
statement. In this example, file is closed after the
with
statement’s suite is finished—even if an exception occurs:
with open('spam.txt', 'w') as file:
file.write('Spam and eggs!')
IOBase
提供以下数据属性和方法:
close
()
刷新并关闭此流。如果文件已经关闭,则此方法无效。文件关闭后,对文件的任何操作(例如读取或写入)都会引发 ValueError
。
为方便起见,允许多次调用此方法。但是,只有第一个调用才会生效。
readlines
(hint=-1)
从流中读取并返回包含多行的列表。 可以指定 hint 来控制要读取的行数:如果(以字节/字符数表示的)所有行的总大小超出了 hint 则将不会读取更多的行。
请注意使用 for line in file: ...
就足够对文件对象进行迭代了,可以不必调用 file.readlines()
。
seek
(offset[, whence])
将流位置修改到给定的字节 offset。 offset 将相对于由 whence 指定的位置进行解析。 whence 的默认值为 SEEK_SET
。 whence 的可用值有:
SEEK_SET
或 0
– 流的开头(默认值);offset 应为零或正值
SEEK_CUR
or 1
– 当前流位置;offset 可以为负值
SEEK_END
or 2
– 流的末尾;offset 通常为负值
返回新的绝对位置。
3.1 新版功能: SEEK_*
常量.
3.3 新版功能: 某些操作系统还可支持其他的值,例如 os.SEEK_HOLE
或 os.SEEK_DATA
。 特定文件的可用值还会取决于它是以文本还是二进制模式打开。
class io.
RawIOBase
原始二进制 I/O 的基类。 它继承自 IOBase
。 没有公共构造器。
原始二进制 I/O 通常提供对下层 OS 设备或 API 的低层级访问,而不尝试将其封装到高层级的基元中(这是留给缓冲 I/O 和 Text I/O 的,将在下文中描述)。
在 IOBase
的属性和方法之外,RawIOBase
还提供了下列方法:
read
(size=-1)
从对象中读取 size 个字节并将其返回。 作为一个便捷选项,如果 size 未指定或为 -1,则返回所有字节直到 EOF。 在其他情况下,仅会执行一次系统调用。 如果操作系统调用返回字节数少于 size 则此方法也可能返回少于 size 个字节。
如果返回 0 个字节而 size 不为零 0,这表明到达文件末尾。 如果处于非阻塞模式并且没有更多字节可用,则返回 None
。
默认实现会转至 readall()
和 readinto()
。
readinto
(b)
Read bytes into a pre-allocated, writable
bytes-like object b, and return the
number of bytes read. If the object is in non-blocking mode and no bytes
are available, None
is returned.
class io.
BufferedIOBase
支持某种缓冲的二进制流的基类。 它继承自 IOBase
。 没有公共构造器。
与 RawIOBase
的主要差别在于 read()
, readinto()
和 write()
等方法将(分别)尝试按照要求读取尽可能多的输入或是耗尽所有给定的输出,其代价是可能会执行一次以上的系统调用。
除此之外,那些方法还可能引发 BlockingIOError
,如果下层的原始数据流处于非阻塞模式并且无法接受或给出足够数据的话;不同于对应的 RawIOBase
方法,它们将永远不会返回 None
。
并且,read()
方法也没有转向 readinto()
的默认实现。
典型的 BufferedIOBase
实现不应当继承自 RawIOBase
实现,而要包装一个该实现,正如 BufferedWriter
和 BufferedReader
所做的那样。
BufferedIOBase
在 IOBase
的现有成员以外还提供或重载了下列方法和属性:
raw
由 BufferedIOBase
处理的下层原始流 (RawIOBase
的实例)。 它不是 BufferedIOBase
API 的组成部分并且不存在于某些实现中。
从缓冲区分离出下层原始流并将其返回。
在原始流被分离之后,缓冲区将处于不可用的状态。
某些缓冲区例如 BytesIO
并无可从此方法返回的单独原始流的概念。 它们将会引发 UnsupportedOperation
。
3.1 新版功能.
read
(size=-1)
读取并返回最多 size 个字节。 如果此参数被省略、为 None
或为负值,则读取并返回所有数据直到 EOF。 如果流已经到达 EOF 则返回一个空的 bytes
对象。
如果此参数为正值,并且下层原始流不可交互,则可能发起多个原始读取以满足字节计数(直至先遇到 EOF)。 但对于可交互原始流,则将至多发起一个原始读取,并且简短的结果并不意味着已到达 EOF。
BlockingIOError
会在下层原始流不处于阻塞模式,并且当前没有可用数据时被引发。
readinto
(b)
Read bytes into a pre-allocated, writable
bytes-like object b and return the number of bytes read.
类似于 read()
,可能对下层原始流发起多次读取,除非后者为交互式。
BlockingIOError
会在下层原始流不处于阻塞模式,并且当前没有可用数据时被引发。
readinto1
(b)
将字节数据读入预先分配的可写 bytes-like object b,其中至多使用一次对下层原始流 read()
(或 readinto()
) 方法的调用。 返回所读取的字节数。
BlockingIOError
会在下层原始流不处于阻塞模式,并且当前没有可用数据时被引发。
3.5 新版功能.
write
(b)
写入给定的 bytes-like object
b,并返回写入的字节数 (总是等于 b 的字节长度,因为如果写入失败则会引发 OSError
)。 根据具体实现的不同,这些字节可能被实际写入下层流,或是出于运行效率和冗余等考虑而暂存于缓冲区。
当处于非阻塞模式时,如果需要将数据写入原始流但它无法在不阻塞的情况下接受所有数据则将引发 BlockingIOError
。
调用者可能会在此方法返回后释放或改变 b,因此该实现应当仅在方法调用期间访问 b。
class io.
FileIO
(name, mode='r', closefd=True, opener=None)
FileIO
代表在 OS 层级上包含文件的字节数据。 它实现了 RawIOBase
接口(因而也实现了 IOBase
接口)。
name 可以是以下两项之一:
代表将被打开的文件路径的字符串或 bytes
对象。 在此情况下 closefd 必须为 True
(默认值) 否则将会引发异常。
代表一个现有 OS 层级文件描述符的号码的整数,作为结果的 FileIO
对象将可访问该文件。 当 FileIO 对象被关闭时此 fd 也将被关闭,除非 closefd 设为 False
。
mode 可以为 'r'
, 'w'
, 'x'
或 'a'
分别表示读取(默认模式)、写入、独占新建或添加。 如果以写入或添加模式打开的文件不存在将自动新建;当以写入模式打开时文件将先清空。 以新建模式打开时如果文件已存在则将引发 FileExistsError
。 以新建模式打开文件也意味着要写入,因此该模式的行为与 'w'
类似。 在模式中附带 '+'
将允许同时读取和写入。
该类的 read()
(当附带正值参数调用时), readinto()
和 write()
方法将只执行一次系统调用。
可以通过传入一个可调用对象作为 opener 来使用自定义文件打开器。 然后通过调用 opener 并传入 (name, flags) 来获取文件对象所对应的下层文件描述符。 opener 必须返回一个打开文件描述符(传入 os.open
作为 opener 的结果在功能上将与传入 None
类似)。
新创建的文件是 不可继承的。
有关 opener 参数的示例,请参见内置函数 open()
。
在 3.3 版更改: 增加了 opener 参数。增加了 'x'
模式。
在 3.4 版更改: 文件现在禁止继承。
在 IOBase
和 RawIOBase
的属性和方法之外,FileIO
还提供了下列数据属性:
mode
构造函数中给定的模式。
class io.
BytesIO
([initial_bytes])
一个使用内存字节缓冲区的流实现。 它继承自 BufferedIOBase
。 在 close()
方法被调用时将会丢弃缓冲区。
可选参数 initial_bytes 是一个包含初始数据的 bytes-like object。
BytesIO
在继承自 BufferedIOBase
和 IOBase
的成员以外还提供或重载了下列方法:
getbuffer
()
返回一个对应于缓冲区内容的可读写视图而不必拷贝其数据。 此外,改变视图将透明地更新缓冲区内容:
>>> b = io.BytesIO(b"abcdef")
>>> view = b.getbuffer()
>>> view[2:4] = b"56"
>>> b.getvalue()
b'ab56ef'
只要视图保持存在,BytesIO
对象就无法被改变大小或关闭。
3.2 新版功能.
class io.
BufferedReader
(raw, buffer_size=DEFAULT_BUFFER_SIZE)
一个提供对可读的序列型 RawIOBase
对象更高层级访问的缓冲区。 它继承自 BufferedIOBase
。 当从此对象读取数据时,可能会从下层原始流请求更大量的数据,并存放到内部缓冲区中。 接下来可以在后续读取时直接返回缓冲数据。
根据给定的可读 raw 流和 buffer_size 创建 BufferedReader
的构造器。 如果省略 buffer_size,则会使用 DEFAULT_BUFFER_SIZE
。
BufferedReader
在继承自 BufferedIOBase
和 IOBase
的成员以外还提供或重载了下列方法:
peek
([size])
从流返回字节数据而不前移位置。 完成此调用将至多读取一次原始流。 返回的字节数量可能少于或多于请求的数量。
class io.
BufferedWriter
(raw, buffer_size=DEFAULT_BUFFER_SIZE)
一个提供对可读的序列型 RawIOBase
对象更高层级访问的缓冲区。 它继承自 BufferedIOBase
。 当写入到此对象时,数据通常会被放入到内部缓冲区中。 缓冲区将在满足某些条件的情况下被写到下层的 RawIOBase
对象,包括:
当缓冲区对于所有挂起数据而言太小时;
当 flush()
被调用时
当(为 BufferedRandom
对象)请求 seek()
时;
当 BufferedWriter
对象被关闭或销毁时。
该构造器会为给定的可写 raw 流创建一个 BufferedWriter
。 如果未给定 buffer_size,则使用默认的 DEFAULT_BUFFER_SIZE
。
BufferedWriter
在继承自 BufferedIOBase
和 IOBase
的成员以外还提供或重载了下列方法:
flush
()
将缓冲区中保存的字节数据强制放入原始流。 如果原始流发生阻塞则应当引发 BlockingIOError
。
class io.
BufferedRandom
(raw, buffer_size=DEFAULT_BUFFER_SIZE)
随机访问流的带缓冲的接口。 它继承自 BufferedReader
和 BufferedWriter
,并进一步支持 seek()
和 tell()
功能。
该构造器会为在第一个参数中给定的可查找原始流创建一个读取器和写入器。 如果省略 buffer_size 则使用默认的 DEFAULT_BUFFER_SIZE
。
BufferedRandom
能做到 BufferedReader
或 BufferedWriter
所能做的任何事。
class io.
BufferedRWPair
(reader, writer, buffer_size=DEFAULT_BUFFER_SIZE)
一个带缓冲的 I/O 对象,它将两个单向 RawIOBase
对象 – 一个可读,另一个可写 – 组合为单个双向端点。 它继承自 BufferedIOBase
。
reader 和 writer 分别是可读和可写的 RawIOBase
对象。 如果省略 buffer_size 则使用默认的 DEFAULT_BUFFER_SIZE
。
BufferedRWPair
实现了 BufferedIOBase
的所有方法,但 detach()
除外,调用该方法将引发 UnsupportedOperation
。
BufferedRWPair
不会尝试同步访问其下层的原始流。 你不应当将传给它与读取器和写入器相同的对象;而要改用 BufferedRandom
。
class io.
TextIOBase
Base class for text streams. This class provides a character and line based
interface to stream I/O. There is no readinto()
method because
Python’s character strings are immutable. It inherits IOBase
.
There is no public constructor.
TextIOBase
在来自 IOBase
的成员以外还提供或重载了以下数据属性和方法:
encoding
用于将流的字节串解码为字符串以及将字符串编码为字节串的编码格式名称。
从 TextIOBase
分离出下层二进制缓冲区并将其返回。
在下层缓冲区被分离后,TextIOBase
将处于不可用的状态。
某些 TextIOBase
的实现,例如 StringIO
可能并无下层缓冲区的概念,因此调用此方法将引发 UnsupportedOperation
。
3.1 新版功能.
seek
(offset[, whence])
将流位置改为给定的偏移位置 offset。 具体行为取决于 whence 形参。 whence 的默认值为 SEEK_SET
。
SEEK_SET
或 0
: 从流的开始位置起查找(默认值);offset 必须为 TextIOBase.tell()
所返回的数值或为零。 任何其他 offset 值都将导致未定义的行为。
SEEK_CUR
或 1
: “查找” 到当前位置;offset 必须为零,表示无操作(所有其他值均不受支持)。
SEEK_END
或 2
: 查找到流的末尾;offset 必须为零(所有其他值均不受支持)。
以数字形式返回新的绝对位置。
3.1 新版功能: SEEK_*
常量.
class io.
TextIOWrapper
(buffer, encoding=None, errors=None, newline=None, line_buffering=False, write_through=False)
一个基于 BufferedIOBase
二进制流的缓冲文本流。 它继承自 TextIOBase
。
encoding 给出流被解码或编码时将使用的编码格式。 它默认为 locale.getpreferredencoding(False)
。
errors 是一个可选的字符串,它指明编码格式和编码格式错误的处理方式。 传入 'strict'
将在出现编码格式错误时引发 ValueError
(默认值 None
具有相同的效果),传入 'ignore'
将忽略错误。 (请注意忽略编码格式错误会导致数据丢失。) 'replace'
会在出现错误数据时插入一个替换标记 (例如 '?'
)。 'backslashreplace'
将把错误数据替换为一个反斜杠转义序列。 在写入时,还可以使用 'xmlcharrefreplace'
(替换为适当的 XML 字符引用) 或 'namereplace'
(替换为 \N{...}
转义序列)。 任何其他通过 codecs.register_error()
注册的错误处理方式名称也可以被接受。
newline 控制行结束符处理方式。 它可以为 None
, ''
, '\n'
, '\r'
和 '\r\n'
。 其工作原理如下:
当从流中读取输入时,如果 newline 为 None
,则会启用 universal newlines 模式。 输入中的行结束符可以为 '\n'
, '\r'
或 '\r\n'
,在返回给调用者之前它们会被统一转写为 '\n'
。 如果参数为 ''
,也会启用通用换行模式,但行结束符会不加转写即返回给调用者。 如果它具有任何其他合法的值,则输入行将仅由给定的字符串结束,并且行结束符会不加转写即返回给调用者。
将输出写入流时,如果 newline 为 None
,则写入的任何 '\n'
字符都将转换为系统默认行分隔符 os.linesep
。如果 newline 是 ''
或 '\n'
,则不进行翻译。如果 newline 是任何其他合法值,则写入的任何 '\n'
字符将被转换为给定的字符串。
如果 line_buffering 为 True
,则当一个写入调用包含换行符或回车时将会应用 flush()
。
如果 write_through 为 True
,对 write()
的调用会确保不被缓冲:在 TextIOWrapper
对象上写入的任何数据会立即交给其下层的 buffer 来处理。
在 3.3 版更改: 已添加 write_through 参数
在 3.3 版更改: 默认的 encoding 现在将为 locale.getpreferredencoding(False)
而非 locale.getpreferredencoding()
。 不要使用 locale.setlocale()
来临时改变区域编码格式,要使用当前区域编码格式而不是用户的首选编码格式。
TextIOWrapper
provides one attribute in addition to those of
TextIOBase
and its parents:
line_buffering
是否启用行缓冲。
class io.
StringIO
(initial_value='', newline='\n')
用于文本 I/O 的内存数据流。 当调用 close()
方法时将会丢弃文本缓冲区。
缓冲区的初始值可通过提供 initial_value 来设置。 如果启用了行结束符转写,换行将以 write()
所用的方式被编码。 数据流位置将被设为缓冲区的开头。
newline 参数的规则与 TextIOWrapper
所用的一致。 默认规则是仅将 \n
字符视为行结束符并且不执行换行符转写。 如果 newline 设为 None
,在所有平台上换行符都将被写入为 \n
,但当读取时仍然会执行通用换行编码格式。
StringIO
在继承自 TextIOBase
及其父类的现有成员以外还提供了以下方法:
getvalue
()
返回一个包含缓冲区全部内容的 str
。 换行符会以与 read()
相同的方式被编码,但是流的位置不会被改变。
用法示例:
import io
output = io.StringIO()
output.write('First line.\n')
print('Second line.', file=output)
# Retrieve file contents -- this will be
# 'First line.\nSecond line.\n'
contents = output.getvalue()
# Close object and discard memory buffer --
# .getvalue() will now raise an exception.
output.close()
16.2.4.1. 二进制 I/O
即使在用户请求单个字节时,也只读取和写入大块数据。通过该方法,缓冲 I/O 也隐藏了调用和执行操作系统无缓冲 I/O 例程时的任何低效性。。增益取决于操作系统和执行的 I/O 类型。例如,在某些现代操作系统上(例如Linux),无缓冲磁盘 I/O 可以与缓冲 I/O 一样快。但最重要的是,无论平台和支持设备如何,缓冲 I/O 都能提供可预测的性能。因此,对于二进制数据,几乎总是首选使用缓冲的I / O而不是未缓冲的I / O。
16.2.4.2. 文本 I/O
二进制存储(如文件)上的文本 I/O 比同一存储上的二进制 I/O 慢得多,因为它需要使用字符编解码器在Unicode和二进制数据之间进行转换。这在处理大量文本数据(如大型日志文件)时会变得非常明显。此外,由于使用的重构算法 TextIOWrapper.tell()
和 TextIOWrapper.seek()
都相当慢。
StringIO
是原生的内存 Unicode 容器,速度与 BytesIO
相似。
16.2.4.3. 多线程
FileIO
对象是线程安全的,只要它们包装的操作系统调用(比如Unix下的 read(2)
)也是线程安全的。
二进制缓冲对象(例如 BufferedReader
, BufferedWriter
, BufferedRandom
和 BufferedRWPair
)使用锁来保护其内部结构;因此,可以安全地一次从多个线程中调用它们。
TextIOWrapper
对象不再是线程安全的。
16.2.4.4. 可重入性
二进制缓冲对象( BufferedReader
, BufferedWriter
, BufferedRandom
和 BufferedRWPair
的实例)不是可重入的。虽然在正常情况下不会发生可重入调用,但是可能会在 signal
处理程序中执行 I/O 而产生。如果线程尝试重新输入已经访问的缓冲对象,则会引发 RuntimeError
。注意,这并不禁止其他线程进入缓冲对象。
上面的内容隐含地扩展到文本文件,因为 open()
函数会把缓冲对象包装在 TextIOWrapper
中。这包括标准流,因此也会影响内置函数 print()
。