Streamlit でアップロードしたファイルのパスを取得して、特定の処理をする
モチベーション
Streamlit は Python code のみで簡単かつ高速に Web アプリを作成できる強力なパッケージ。 Streamplit で作られた Web アプリ経由でファイルをアップロードして、そのファイルを処理したい際の具体的な実現方法がなかったので備忘録がてら残しておく。
PDF ファイルをアップロードして、画像に変換する Web アプリ
具体的に例を交えつつ説明する。
Streamlit を使って、PDF ファイルをアップロードしてアップロードされた PDF ファイルを画像化するアプリを作成する。
今回は、Belval/pdf2image という PDF パッケージを使用する。
このパッケージは処理したい PDF のファイルパスを要求するインターフェースなので今回の実例に沿っていてわかりやすい。
ローカルマシンは MacOS を想定しており、pdf2image
はpoppler の事前インストールが必須。
完成形のスクリーンショット
GitHub でもコードを公開しておきました。
hurutoriya/streamlist-file-uploader-example
デモ動画はこちら
Makefile
Makefile は依存パッケージを事前インストールするために採用
install:
brew install poppler
poetry install
run:
poetry run streamlit run streamlit_pdf_uploader/main.py
Poetry for package management
環境構築は poetry を使っています。
[tool.poetry]
name = "streamlit-pdf-uploader"
version = "0.1.0"
description = ""
authors = [""]
[tool.poetry.dependencies]
python = "^3.8"
streamlit = "^0.84.0"
watchdog = "^2.1.3"
pdf2image = "^1.16.0"
[tool.poetry.dev-dependencies]
pytest = "^5.2"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
Streamlit Python file
import base64
import tempfile
import streamlit as st
from pdf2image import convert_from_path
from pathlib import Path
def show_pdf(file_path:str):
"""Show the PDF in Streamlit
That returns as html component
Parameters
----------
file_path : [str]
Uploaded PDF file path
"""
with open(file_path, "rb") as f:
base64_pdf = base64.b64encode(f.read()).decode("utf-8")
pdf_display = f'<embed src="data:application/pdf;base64,{base64_pdf}" width="100%" height="1000" type="application/pdf">'
st.markdown(pdf_display, unsafe_allow_html=True)
def main():
"""Streamlit application
"""
st.title("PDF file uplodaer")
uploaded_file = st.file_uploader("Choose your .pdf file", type="pdf")
if uploaded_file is not None:
# Make temp file path from uploaded file
with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
st.markdown("## Original PDF file")
fp = Path(tmp_file.name)
fp.write_bytes(uploaded_file.getvalue())
st.write(show_pdf(tmp_file.name))
imgs = convert_from_path(tmp_file.name)
st.markdown(f"Converted images from PDF")
st.image(imgs)
if __name__ == "__main__":
main()
Conclusion
これで、Streamlit 上でファイルをアップロードして、そのアップロードされたファイルに対する処理ができます。 画像や音声など色々応用先があるので便利そう。 動作が遅いという欠点はあれど、これだけ簡単に GUI を Python のみで構築できるのは驚き。 Protly Dash も 2 年ほど前に使ったことがあるけど、UI のライフサイクルや HTML を結構意識しないとかけなかったので辛かった記憶があるので、なおさら感動している。
Reference
関連しているかもしれない記事
- Poetry からsetup.py を自動生成する
- KyTeaをPythonで扱えるMykyteaを使うために必要なこと
- Pythonで変数を挿入してSQLクエリを柔軟に構築する
- pipenv のversion 2020.11.15 でローカルパッケージが正常にインストールされないときの対処法
- pip 実行時に sys.stderr.write(f"ERROR: {exc} ") とエラーが出てpipを実行できないときの対処方法
📮 📧 🐏: 記事への感想のおたよりをおまちしてます。 お気軽にお送りください。 メールアドレス入力があればメールで返信させていただきます。 もちろんお返事を希望せずに単なる感想だけでも大歓迎です。
このサイトの更新情報をRSSで配信しています。 お好きなフィードリーダーで購読してみてください。
このウェブサイトの運営や著者の活動を支援していただける方を募集しています。 もしよろしければ、Buy Me a Coffee からサポート(投げ銭)していただけると、著者の活動のモチベーションに繋がります✨
Amazonでほしいものリストも公開しているので、こちらからもサポートしていただけると励みになります。