私はPythonでストリームを操作することを学んでいますが、 IO docs が次のように言っていることに気付きました:
バイナリストリームを作成する最も簡単な方法は、モード文字列に 'b'を指定したopen()を使用することです。
f = open("myfile.jpg", "rb")
インメモリバイナリストリームは、BytesIOオブジェクトとしても利用できます。
f = io.BytesIO(b"some initial binary data: \x00\x01")
f
で定義されているopen
とf
で定義されているBytesIO
の違いは何ですか。言い換えれば、「インメモリバイナリストリーム」を構成するものと、open
の機能との違いは何ですか?
簡単にするために、今は読む代わりに書くことを考えてみましょう。
したがって、次のように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"
を1つずつ連結するよりも高速にするいくつかの最適化を実行できます。
ここにそれを証明するための小さなベンチマークがあります:
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.例に関連して:f.close()
を呼び出す代わりにwithステートメントを使用している
open
を使用すると、ハードドライブ上のファイルが開きます。使用するモードに応じて、ディスクから読み取りまたは書き込み(または両方)を実行できます。
BytesIO
オブジェクトは、ディスク上の実際のファイルに関連付けられていません。ファイルのように動作するメモリの塊です。 open
から返されるファイルオブジェクトと同じAPIを使用します(モードr+b
で、バイナリデータの読み取りと書き込みが可能)。
BytesIO
(そして、常に兄弟であるStringIO
は常にテキストモードです)は、ファイルオブジェクトが与えられることを期待しているAPIにデータを渡す必要があるときに便利です。データを直接渡すことを好みます。ライブラリに渡す前に、入力データをBytesIO
にロードできます。戻った後、getvalue()
メソッドを使用して、ライブラリがBytesIO
からファイルに書き込んだデータを取得できます。 (通常、それらのうちの1つを実行するだけで十分です。)
f = open("myfile.jpg", "rb")
ディスクdiskからファイルからバイトを読み取り、メモリ内のPythonによって保持される 'f'として参照されるオブジェクトにそのような値を割り当てます。
f = io.BytesIO(b"some initial binary data: \x00\x01")
バイトストリーム値を、メモリ内のPythonによって保持される 'f'として参照されるオブジェクトに割り当てます。