0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

StreamlitアプリをRenderで本番デプロイして学んだ「ファイルバッファ」の仕組み

Posted at

はじめに

先日、Streamlitで作ったアプリをRenderにデプロイしたところ、ローカルでは動いたのに本番環境では画像読み込みでエラーが出ました。
調べて修正していくうちに、ファイルバッファの仕組みを理解する良いきっかけになったので共有します。


ローカルで動いても本番で落ちる理由

Streamlitのst.file_uploaderで受け取れるのは「ファイルそのもの」ではなく、**ファイルバッファ(file buffer)**と呼ばれるオブジェクトです。

  • ファイルバッファ = ファイルを読むための窓口(ストリーム+読み取り位置つき)
  • .read() を呼ぶと「しおり」が進み、次は続きからしか読めない

ローカル環境ではたまたま問題が出なくても、本番環境(Renderなど)ではファイルの扱い方が少し違うため、**「2回目に読めない」「I/Oエラー」**といった不具合が表面化します。


解決のポイント

  1. バイト列に吸い上げる

    file_bytes = file_buffer.read()
    pil_image = Image.open(io.BytesIO(file_bytes))
    

    → 生データをコピーすることで、環境の差を吸収。

  2. しおりをリセットする

    file_buffer.seek(0)
    

    → 同じfile_bufferを後で使うなら、必ず先頭に戻す。

  3. 例外をユーザーに見せる

    except Exception as e:
        st.error(f"画像の読み込みに失敗しました: {str(e)}")
        st.stop()
    

    → 黒画面クラッシュを防ぎ、原因がわかるようにする。


最終コード(抜粋)

def load_image_as_bgr(file_buffer):
    try:
        file_bytes = file_buffer.read()
        pil_image = Image.open(io.BytesIO(file_bytes))
        file_buffer.seek(0)

        img_array = np.array(pil_image)
        if len(img_array.shape) == 3:
            img_bgr = cv2.cvtColor(img_array, cv2.COLOR_RGB2BGR)
        else:
            img_bgr = cv2.cvtColor(img_array, cv2.COLOR_GRAY2BGR)
        return img_bgr

    except Exception as e:
        st.error(f"画像の読み込みに失敗しました: {str(e)}")
        st.stop()

まとめ

  • ファイルバッファ = ストリーム+しおり
  • 本番環境ではI/Oの仕組みがローカルと違うため、不具合が出やすい
  • bytes化 → seek(0) → 例外処理 の3ステップで安定

おわりに

今回学んだ「ファイルバッファ」という考え方は、PythonやStreamlitに限らず、Webアプリや他の言語でもよく登場する基本的な仕組みです。 自分は今回、ローカルでは動くのに本番で落ちたことで初めて気づきましたが、中身を知れば怖くないです。

同じようにハマった方の参考になれば嬉しいです。


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?