コンテンツにスキップ

WindowsのタスクトレイでPythonスクリプトを実行

[質問]

WindowsのPythonでローカルWebサーバーを動かすとき、アイコンをタスクトレイに入れられますか

[回答] Grok

はい、WindowsのPythonでローカルWebサーバーを動かしながら、タスクトレイ(システムトレイ)にアイコンを表示することは可能です。

主なおすすめ方法は、pystray ライブラリを使うことです。軽量でクロスプラットフォーム対応(Windows含む)で、メニュー(停止・ブラウザで開くなど)も簡単に追加できます。

必要なライブラリ

  • pystray:タスクトレイアイコン用
  • Pillow(PIL):アイコン画像を作成・扱うため
  • Webサーバー部分は標準ライブラリの http.serverFlask/FastAPI などを使います。

インストール:

pip install pystray pillow

基本的な実装例(http.server + pystray)

Webサーバーを別スレッドで起動し、タスクトレイアイコンを表示する例です。icon.run() がブロッキングなので、スレッドを組み合わせます。

import threading
import http.server
import socketserver
import pystray
from PIL import Image, ImageDraw
import webbrowser
import sys

# ------------------- Webサーバー部分 -------------------
PORT = 8000
Handler = http.server.SimpleHTTPRequestHandler  # カレントディレクトリをサーブ

def run_server():
    with socketserver.TCPServer(("", PORT), Handler) as httpd:
        print(f"サーバー起動: http://localhost:{PORT}")
        httpd.serve_forever()

# ------------------- タスクトレイアイコン部分 -------------------
def create_image():
    """シンプルなアイコン画像を作成(64x64)"""
    image = Image.new('RGB', (64, 64), color=(0, 120, 215))  # 青背景
    dc = ImageDraw.Draw(image)
    dc.text((10, 20), "WS", fill=(255, 255, 255))  # "WS" = Web Server
    return image

def on_open(icon, item):
    """メニューから「開く」を選んだとき"""
    webbrowser.open(f"http://localhost:{PORT}")

def on_quit(icon, item):
    """終了"""
    icon.stop()
    sys.exit(0)

# メニュー定義
menu = pystray.Menu(
    pystray.MenuItem("ブラウザで開く", on_open),
    pystray.MenuItem("終了", on_quit)
)

# アイコン作成
icon = pystray.Icon(
    "local_web_server",          # 内部名
    icon=create_image(),         # アイコン画像
    title=f"Local Server (port {PORT})",  # ホバー時のツールチップ
    menu=menu
)

# ------------------- メイン処理 -------------------
if __name__ == "__main__":
    # Webサーバーを別スレッドで起動
    server_thread = threading.Thread(target=run_server, daemon=True)
    server_thread.start()

    # タスクトレイアイコンを表示(ブロッキング)
    icon.run()

ポイントとTips

  • サーバーとトレイの同時動作http.server.serve_forever() はブロッキングなので、必ず threading.Thread(または concurrent.futures)で別スレッドにします。daemon=True にするとメイン終了時に自動停止しやすくなります。
  • FlaskやFastAPIを使う場合:同様にサーバー起動をスレッド(または app.run(threaded=True))にすればOKです。
  • カスタムアイコンcreate_image() の代わりに .ico.png ファイルを Image.open("icon.png") で読み込めます。
  • 右クリックメニュー:停止、再起動、ポート変更、ログ表示などを追加しやすいです。
  • コンソール非表示で起動.pyw 拡張子で保存するか、PyInstallerなどでexe化するときに --noconsole オプションを使います。
  • PyInstallerでexe化pystray + pillow を含めてexeにすると、単独実行可能になります(アイコンファイルも一緒にバンドル)。

他の選択肢

  • Qt/PySide6やPyQt6QSystemTrayIcon を使うとよりリッチな通知やメニューが作れますが、重めです。
  • 古い方法pywin32 + 自前Win32 API呼び出し(SysTrayIcon.pyなど)もありますが、pystrayの方が現代的で簡単です。

この方法で、Webサーバーがバックグラウンドで動きつつ、タスクトレイに常駐アイコンが表示され、右クリックで操作できるアプリになります。

実際に試してみて、メニューを拡張したい場合やFlask版が欲しい場合は、追加で教えてください!