軽量Pythonフレームワーク「Bottle」でシンプルなWebアプリを作る

軽量Pythonフレームワーク「Bottle」でシンプルなWebアプリを作る

Pythonでウェブアプリケーションを開発する際、DjangoやFlaskが真っ先に思い浮かぶ人も多いでしょう。しかし、シンプルで軽量なフレームワークをお探しでしたら、Bottle をお勧めします。
最近、Bottleについて学び、それを活用してQRコード生成ウェブアプリケーション「QRCode Maker」を作成しました。この記事では、Bottleの特徴や利点、そして実際の実装例をご紹介します。

Bottleとは?

Bottle は、Python用の軽量なマイクロフレームワークです。DjangoやFlaskと比較すると、機能を最小限に抑えた設計が特徴で、以下のような特性があります。

Bottleの主な特徴

1. 極めてシンプルな構成

  • 依存関係が少なく、標準ライブラリのみで動作
  • インストールはpipで簡単にでき、依存ライブラリはほぼなし
  • 学習曲線が浅く、初心者にも優しい

2. 単一ファイルで構成可能

  • フレームワーク全体がほぼ単一のPythonファイルで実装されている
  • 小〜中規模のアプリケーションであれば、1ファイルで完結できる
  • デプロイが簡単

3. シンプルなルーティング

  • URLパターンマッチングが直感的
  • デコレータを使った美しいルート定義

4. テンプレートエンジン組込

  • シンプルなテンプレートシステムが内包されている
  • 別途テンプレートエンジンをインストールする必要がない

5. 軽量で高速

  • 不要な機能を削ぎ落としているため、メモリ効率が良い
  • 小規模なプロジェクトやマイクロサービスに適している
from bottle import Bottle, run

app = Bottle()

@app.route('/hello')
def hello():
    return 'Hello World!'

run(app, host='localhost', port=8080)

たった数行で、簡単なウェブサーバーが起動します。Bottleのシンプルさが伝わってきますね。

QRCode Makerの実装

では、実際にBottleを使って作成したQRCode Makerのアプリケーションをご紹介します。

プロジェクト構成

qrcode_maker/
  app.py          # Bottleアプリケーションメイン
  wifi_qr.py      # QRコード生成ロジック
  requirements.txt
  tests/          # テスト

必要なライブラリ

qrcode[pil]>=8.0
bottle>=0.13

qrcode はQRコード画像生成用、bottle はウェブフレームワークです。

アプリケーションの構造

app.py - Bottleアプリケーションのメインファイル

from bottle import Bottle, request, response, run, template
from wifi_qr import create_qr_png_bytes, make_wifi_payload

app = Bottle()
DEFAULT_HOST = "127.0.0.1"
# 8080ポートは、自宅のPCで他のアプリで使われているため8081ポートにしている
DEFAULT_PORT = 8081

@app.route('/')
def index():
    # ホームページを表示するロジック
    return template(PAGE_TEMPLATE)

@app.route('/api/generate', method='POST')
def generate_qr():
    # POSTデータを取得
    ssid = request.forms.get('ssid')
    password = request.forms.get('password')
    security = request.forms.get('security')
    
    # QRコード生成
    payload = make_wifi_payload(ssid, password, security)
    qr_image = create_qr_png_bytes(payload)
    
    # 画像をレスポンスで返す
    response.content_type = 'image/png'
    return qr_image

if __name__ == '__main__':
    run(app, host=DEFAULT_HOST, port=DEFAULT_PORT)

wifi_qr.py - QRコード生成ロジック

import qrcode
from io import BytesIO

def escape_wifi_value(value: str) -> str:
    """Wi-Fiペイロード用の特殊文字エスケープ \;,:\"の文字の前にバックスラッシュをつける"""
    return "".join(f"\\{char}" if char in r"\;,:\"" else char for char in value)

def make_wifi_payload(ssid: str, password: str, security: str = "WPA", hidden: bool = False) -> str:
    """Wi-Fi設定用QRコードペイロード生成"""
    security = security.upper()
    if security not in {"WPA", "WEP", "NOPASS"}:
        raise ValueError("security must be WPA, WEP, or nopass")
    
    fields = [f"T:{security}", f"S:{escape_wifi_value(ssid)}"]
    if security != "NOPASS":
        fields.append(f"P:{escape_wifi_value(password)}")
    if hidden:
        fields.append("H:true")
    
    return "WIFI:" + ";".join(fields) + ";;"

def create_qr_png_bytes(data: str, box_size: int = 10, border: int = 4) -> bytes:
    """QRコードPNG画像をバイト列で返す"""
    qr = qrcode.QRCode(
        version=None,
        error_correction=qrcode.constants.ERROR_CORRECT_M,
        box_size=box_size,
        border=border,
    )
    qr.add_data(data)
    qr.make(fit=True)
    
    image = qr.make_image(fill_color="black", back_color="white")
    
    img_bytes = BytesIO()
    image.save(img_bytes, format='PNG')
    return img_bytes.getvalue()

Bottleを選んだ理由

このプロジェクトでBottleを採用した理由は以下の通りです。

  1. シンプル性

    • 小規模で単純な機能のアプリケーションに最適
    • ボイラープレートコードが少ない

    ボイラープレートコードとは、アプリの本質的な処理ではなく、同じように何度も書かれる「定型的な準備コード」のことです。

    たとえば、Webアプリなら「ルーティングの設定」や「サーバー起動処理」「設定読み込み」など
    これらは毎回必要になるけれど、アプリの固有機能ではない

  2. 依存関係の少なさ

    • インストール時の依存ライブラリが最小限
    • デプロイが簡単で、環境構築のトラブルが少ない
  3. 学習効果

    • ウェブフレームワークの基礎を学ぶのに最適
    • 各機能の動作原理が理解しやすい
  4. パフォーマンス

    • 軽量なため、少ないリソースで動作
    • ローカル開発環境に最適

Bottleの活用シーン

Bottleは以下のようなシーンで特に活躍します。

1. プロトタイピング

素早くアイデアを形にしたい場合、Bottleの手軽さは大きな利点です。

2. マイクロサービス

軽量で依存関係が少ないため、マイクロサービスアーキテクチャに向いています。

3. IoTデバイス上でのサーバー

リソースが限定されたデバイスでも動作させやすい。

4. ローカル開発ツール

このQRCode Makerのように、チーム内で利用する小規模ツール。

5. APIサーバー

シンプルなRESTful APIの構築に最適。

Flask や Django との比較

参考として、Bottleとほかのフレームワークを比較してみます。

項目 Bottle Flask Django
学習曲線 非常に浅い 浅い
機能の豊富さ 最小限 中程度 充実
プロジェクト規模 小〜中 小〜大 中〜大
依存関係 ほぼなし 少ない 多い
デプロイ難易度 簡単 中程度 複雑

実装のポイント

QRCode Makerを実装する際、Bottleで活用した機能をいくつかご紹介します。

ルーティング

@app.route('/')
def index():
    pass

@app.route('/api/generate', method='POST')
def generate_qr():
    pass

HTTPメソッドや複数ルートを簡単に定義できます。

フォームデータの取得

ssid = request.forms.get('ssid')
password = request.forms.get('password')

request オブジェクトからフォームデータを直感的に取得できます。

レスポンスのカスタマイズ

response.content_type = 'image/png'
return qr_image

Content-Typeを指定して、異なるデータ形式(HTML、JSON、画像など)を返せます。

テンプレートの利用

Bottleには簡単なテンプレートエンジンが組み込まれており、HTMLページを動的に生成できます。

Bottleの限界と使い分け

Bottleは素晴らしいフレームワークですが、すべてのプロジェクトに適しているわけではありません。

Bottleが向いていないシーン

  • 大規模なエンタープライズアプリケーション

    • Djangoの充実した機能が必要
  • 複雑なビジネスロジック

    • フレームワークレベルのサポートが必要になる
  • 複数の開発者による共同開発

    • 規約や構造が明確なDjangoが適している
  • 複数のデータベースを扱う場合

    • ORMなどのサポートが少ない

使い分けの指針

  • Bottle: 小〜中規模、シンプル、軽量、学習用
  • Flask: 小〜大規模、柔軟性が必要、拡張予定あり
  • Django: 大規模、ORM・認証・管理画面などが必要、チーム開発

終わりに

Bottleは「小さく始めたい」「シンプルに作りたい」というPythonプログラマーの声に応えるフレームワークです。このQRCode Makerプロジェクトを通じて、Bottleの持つ軽量さと実用性を実感することができました。

ウェブアプリケーション開発をはじめたばかりの方や、プロトタイピングの効率化を目指す方は、ぜひBottleを試してみてください。シンプルなコードで思いのままのウェブアプリを素早く構築できる喜びを感じられるはずです。


今回紹介したQRCode Makerプロジェクト:

  • Wi-Fi接続情報からQRコードを自動生成
  • AndroidとiOS対応
  • ローカルホストで動作する軽量ウェブアプリ

Bottleの可能性はまだまだ広がっています。あなたの次のプロジェクトでも、Bottleの活躍の場が見つかるかもしれません!