[解決済み] バイナリストリームにおける `open` と `io.BytesIO` の相違点
質問
Pythonでストリームの扱いについて学んでいるのですが、その中で IO ドキュメント は次のように言っています。
バイナリストリームを作成する最も簡単な方法は、モード文字列に '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
というファイルが作成され、その中に 3x
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.3529 秒
- バイトIO: 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()
関連
-
[解決済み] staticmethodとclassmethodの違いについて
-
[解決済み] Pythonのリストメソッドであるappendとextendの違いは何ですか?
-
[解決済み] 0から9までのランダムな整数を生成する
-
[解決済み] リストにおけるdel、remove、popの違いについて
-
[解決済み] リストとタプルの違いは何ですか?
-
[解決済み] 2つのリストの差を取得する
-
[解決済み] 組込み開関数におけるモードa、a+、w、w+、r+の違い?
-
[解決済み】__str__と__repr__の違いは何ですか?
-
[解決済み】venv, pyvenv, pyenv, virtualenv, virtualenvwrapper, pipenvなどの違いは何ですか?
-
[解決済み】Djangoでnull=Trueとblank=Trueの違いは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Djangoで2つの日付の間を選択する
-
[解決済み] バブルソートの宿題
-
[解決済み] 辞書のキーと値を交換するにはどうすればよいですか?
-
[解決済み] dict を txt ファイルに書き、それを読み取る?
-
[解決済み] Pythonのインスタンス変数とクラス変数
-
[解決済み] virtualenv の `--no-site-packages` オプションを元に戻す。
-
[解決済み] Pythonでファイルの読み込みと上書きをする
-
[解決済み] Pythonの文字列書式をリストで使う
-
[解決済み] 単純な文字列からtimedeltaオブジェクトを作成する方法
-
[解決済み] Django filter queryset __in for *every* item in list