Skip to content

QRコード生成(qrcode)


qrcode ライブラリ

使い方はめっちゃ簡単。

import qrcode

img = qrcode.make("FastAPI")
img.save("qrcode-test.png") # type: ignore

qrcode-test.png を生成できる。

qrcode.make で生成した QR コード


QR コード生成エンドポイント

qrcode を使って、 URL を渡すと QR コードの画像を返すエンドポイントを作る。

from fastapi import FastAPI, Query, Response
from pydantic import HttpUrl
import qrcode
from io import BytesIO

app = FastAPI()

@app.get("/generate-qr")
async def generate_qr(url: HttpUrl = Query(...)):
    img = qrcode.make(str(url))
    buf = BytesIO()
    img.save(buf, format="PNG")  # type: ignore

    return Response(content=buf.getvalue(), media_type="image/png")

generate-qr エンドポイントで生成した QR コード


io モジュールの BytesIO

cf. io — Binary I/O / io.BytesIO

img.save("qrcode-test.png") みたいに書くと、ディスクへの書き込みが行われるので遅いし、同時にリクエストが来たら上書きとかロックとかが起こるかもしれない。
io.BytesIO を使えば、リクエストごとにメモリを確保して処理できる。

Quote

A binary stream using an in-memory bytes buffer.
https://docs.python.org/3.14/library/io.html#io.BytesIO より

なので、下記のように書いて buf に QR コードを書き込んでいくようにするといい。

    img = qrcode.make("FastAPI")
    buf = BytesIO()
    img.save(buf, format="PNG")  # type: ignore

あとは bufgetvaluebytes にして Response で返すだけ。 getvalue は現在位置に関係なくバッファ全体を返すので、 buf.seek(0) も要らない。

StreamingResponsebuf をそのまま渡す手もあって、その場合は getvalue のコピー 1 回分を減らせる。ただ StreamingResponse が本領を発揮するのは、ジェネレータやファイルをチャンクで逐次返すときで、 QR コードみたいに成果物が全部メモリにある小さいデータだと差はごくわずか。なのでここは素直に Response でOK。

Response / StreamingResponse / FileResponse の使い分け

  • Response — 成果物が全部メモリにある小さいデータ( QR コードや 1 枚の PDF など)。 content=bytes で素直に返せて、ヘッダーも付けやすい。
  • StreamingResponse — ジェネレータやファイルをチャンクで逐次返すとき。全体をメモリに載せずに流せるので、大きいデータほど効く。
  • FileResponse — すでにディスクにあるファイルをそのまま返すとき。