7
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?

シェルスクリプトはもう古い?PEP 723とuvで書く「1ファイル完結型」のモダンPython自動化スクリプト

7
Posted at

なぜ、いまだにシェルスクリプトで消耗しているのか

Linux上の定常作業や自動化タスクにおいて、Bashなどのシェルスクリプトは便利だが、少し複雑な処理(JSONパース、API連携、並列処理など)を行おうとすると、途端に可読性が低下し、メンテナンスが困難になる。

Pythonで書き直したいところだが、サードパーティ製ライブラリ(requestspsutilなど)に依存すると、実行環境ごとにpip installvenvの構築が必要になり、ポータビリティが失われる。

このジレンマを解決するのが、**PEP 723(Inline script metadata)と、Rust製の超高速Pythonパッケージマネージャーuv**の組み合わせだ。これを使えば、スクリプト内に依存関係を記述し、完全に「単一ファイル」でポータブルに実行できる。

現代の最適解:PEP 723 + uv

PEP 723は、Pythonスクリプトの中に、そのスクリプトが必要とする依存ライブラリやPythonの要求バージョンをコメント形式で直接埋め込める仕様だ。

そして、Astral社が開発するuvを使用すれば、実行時にその依存関係を自動的かつ高速に一時環境へインストールし、スクリプトを実行してくれる。ホスト環境を汚すことは一切ない。

実践:システム情報を収集して通知するモダンスクリプト

以下は、Linuxのシステムリソース情報を監視し、サードパーティライブラリであるpsutilrequestsを使用して整形・送信する実用的な自動化スクリプトだ。

# /// script
# requires-python = ">=3.11"
# dependencies = [
#     "psutil>=5.9.0",
#     "requests>=2.31.0",
# ]
# ///

import os
import socket
import psutil
import requests

def get_system_stats():
    cpu_usage = psutil.cpu_percent(interval=1)
    memory = psutil.virtual_memory()
    disk = psutil.disk_usage('/')
    
    return {
        "hostname": socket.gethostname(),
        "cpu": f"{cpu_usage}%",
        "memory": f"{memory.percent}% (Used: {memory.used // (1024**2)}MB / Total: {memory.total // (1024**2)}MB)",
        "disk": f"{disk.percent}%"
    }

def send_to_webhook(stats):
    # 環境変数からWebhook URLを取得
    webhook_url = os.getenv("MONITOR_WEBHOOK_URL")
    if not webhook_url:
        print("Error: MONITOR_WEBHOOK_URL environment variable is not set.")
        print(f"[DEBUG] Stats: {stats}")
        return

    payload = {
        "text": f"🚨 **System Monitor Alert - {stats['hostname']}** 🚨\n"
                f"- **CPU Usage:** {stats['cpu']}\n"
                f"- **Memory Usage:** {stats['memory']}\n"
                f"- **Disk Usage:** {stats['disk']}"
    }
    
    response = requests.post(webhook_url, json=payload)
    if response.status_code in (200, 204):
        print("Successfully sent system stats to webhook.")
    else:
        print(f"Failed to send. Status: {response.status_code}, Response: {response.text}")

if __name__ == "__main__":
    stats = get_system_stats()
    send_to_webhook(stats)

このスクリプトの何が革命的なのか?

スクリプトの先頭部分に注目してほしい。

# /// script
# requires-python = ">=3.11"
# dependencies = [
#     "psutil>=5.9.0",
#     "requests>=2.31.0",
# ]
# ///

これがPEP 723で規定されたメタデータだ。
このスクリプト(名前を monitor.py とする)を実行するにあたり、事前に pip install を行う必要は一切ない。

以下のコマンドを実行するだけで自動的に実行環境が構築される。

# uvのインストール(未導入の場合のみ、一瞬で完了する)
curl -LsSf https://astral.sh/uv/install.sh | sh

# スクリプトの実行
uv run monitor.py

uv は、スクリプト内のメタデータを自動で解析し、必要なライブラリを隔離された一時的なキャッシュ領域にロードして、即座にスクリプトを実行する。2回目以降の実行は、キャッシュが効くためミリ秒単位で超高速に起動する。

実務における3大メリット

  1. 「環境が壊れる」問題からの完全な解放
    システム全体のPython(System Python)やグローバル環境にライブラリをインストールしないため、OSのパッケージ管理を汚染するリスクがゼロになる。
  2. 圧倒的なポータビリティ
    Gitリポジトリにこの1ファイルをコミットしておくだけで、他のLinuxサーバーでも、uv run さえ叩けば全く同じように動作する。requirements.txtpyproject.toml も不要だ。
  3. Cronとの相性の良さ
    Cronなどのジョブスケジューラから呼び出す際も、仮想環境の有効化(source venv/bin/activate)のような冗長な前処理が不要になる。
# Crontabでの設定例
0 * * * * export MONITOR_WEBHOOK_URL="https://your-webhook-url" && /usr/local/bin/uv run /path/to/monitor.py

結論

これからのLinux自動化は、「書きづらいシェルスクリプト」か「管理が面倒なPythonプロジェクト」かという二者択一ではない。
PEP 723とuvによる**「単一ファイル完結型のモダンPythonスクリプト」**こそが、これからのインフラ・開発運用のデファクトスタンダードである。今すぐ手元のスクリプトをこの構成に書き換え、運用の手間を最小限に抑えるべきだ。

7
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
7
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?