二进制流中“open”和“io.BytesIO”的区别

2024-03-29 03:04:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在学习使用Python中的streams,我注意到IO docs表示如下:

The easiest way to create a binary stream is with open() with 'b' in the mode string:

f = open("myfile.jpg", "rb")

In-memory binary streams are also available as BytesIO objects:

f = io.BytesIO(b"some initial binary data: \x00\x01")

open定义的f与由BytesIO定义的f之间的区别是什么。换句话说,“内存中的二进制流”是由什么构成的?它与open的功能有什么不同?


Tags: thetoiodocsstream定义iscreate
3条回答

使用open在硬盘上打开一个文件。根据使用的模式,您可以从磁盘读取或写入(或同时读取和/或写入)。

BytesIO对象与磁盘上的任何实际文件都没有关联。它只是一块内存,其行为类似于文件。它与从open返回的文件对象具有相同的API(使用模式r+b,允许读取和写入二进制数据)。

BytesIO(而且它是近亲StringIO,始终处于文本模式)在需要将数据传递到或从期望给定文件对象但希望直接传递数据的API传递数据时非常有用。在将输入数据提供给库之前,可以将其加载到BytesIO中。在它返回之后,您可以使用getvalue()方法从BytesIO中获取库写入文件的任何数据。(当然,通常你只需要做其中一个。)

为了简单起见,现在让我们考虑写作而不是阅读。

所以当你用open()比如说:

with open("test.dat", "wb") as f:
    f.write(b"Hello World")
    f.write(b"Hello World")
    f.write(b"Hello World")

执行后,将创建名为test.dat的文件,其中包含Hello World。数据写入文件后不会保存在内存中(除非用名称保存)。

现在当你考虑io.BytesIO()时:

with io.BytesIO() as f:
    f.write(b"Hello World")
    f.write(b"Hello World")
    f.write(b"Hello World")

它不是将内容写入文件,而是写入内存缓冲区。换句话说就是一块内存。基本上,写下以下内容是等效的:

buffer = b""
buffer += b"Hello World"
buffer += b"Hello World"
buffer += b"Hello World"

对于带有with语句的示例,最后还会有一个del buffer

这里的关键区别在于优化和性能。io.BytesIO能够进行一些优化,使其比简单地逐个连接所有b"Hello World"更快。

为了证明这是一个小基准:

  • Concat:1.3529秒
  • 字节:0.0090秒

import io
import time

begin = time.time()
buffer = b""
for i in range(0, 50000):
    buffer += b"Hello World"
end = time.time()
seconds = end - begin
print("Concat:", seconds)

begin = time.time()
buffer = io.BytesIO()
for i in range(0, 50000):
    buffer.write(b"Hello World")
end = time.time()
seconds = end - begin
print("BytesIO:", seconds)

除了性能提高之外,使用BytesIO而不是连接还具有BytesIO可以代替文件对象的优点。假设有一个函数需要一个文件对象写入。然后你可以给它一个内存缓冲区而不是一个文件。

区别在于open("myfile.jpg", "rb")只是加载并返回myfile.jpg的内容;而BytesIO又是一个包含一些数据的缓冲区。

由于BytesIO只是一个缓冲区-如果以后要将内容写入文件,则必须执行以下操作:

buffer = io.BytesIO()
# ...
with open("test.dat", "wb") as f:
    f.write(buffer.getvalue())

另外,您没有提到版本;我使用的是Python3。与示例相关:我使用with语句而不是调用f.close()

f = open("myfile.jpg", "rb")

从磁盘读取文件中的字节,并将该值分配给被Python保存在内存中的被引用为“f”的对象。

f = io.BytesIO(b"some initial binary data: \x00\x01")

将字节流值赋给被引用为“f”的对象,该对象由Python保存在内存中。

相关问题 更多 >