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

时间:2017-03-15 02:49:28

标签: python io stream

我正在学习如何在Python中使用流,我注意到IO docs说了以下内容:

  

创建二进制流的最简单方法是在模式字符串中使用open()和'b':

     

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

     

内存中的二进制流也可用作BytesIO对象:

     

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

f定义的openf定义的BytesIO之间有何区别?换句话说,什么是“内存中的二进制流”,它与open的不同之处是什么?

3 个答案:

答案 0 :(得分:51)

为简单起见,我们暂时考虑写作而不是阅读。

所以,当您使用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")

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

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秒
  • BytesIO: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())

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

答案 1 :(得分:6)

使用open打开硬盘上的文件。根据您使用的模式,您可以从磁盘读取或写入(或两者)。

BytesIO对象与磁盘上的任何实际文件无关。它只是一块内存,就像文件一样。它与从open返回的文件对象具有相同的API(模式r+b,允许读取和写入二进制数据)。

BytesIO(并且它总是处于文本模式时,它是紧密的兄弟StringIO)当您需要将数据传入或传出期望获得文件对象的API时,它会非常有用,但是你更喜欢直接传递数据。在将输入数据提供给库之前,您可以将其输入BytesIO。返回后,您可以使用BytesIO方法从getvalue()获取库写入文件的任何数据。 (当然,你通常只需要做其中一个。)

答案 2 :(得分:0)

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

从磁盘磁盘中读取文件中的字节,并将此值赋给引用为'f'的对象,该对象由Python保存在内存中。

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

将字节流值分配给引用为'f'的对象,该对象由Python保存在内存中。