概要(Slack 通知は「コードからチャンネルにしゃべらせる」技)
Slack 通知は、
「Python のスクリプトが、自動で Slack のチャンネルにメッセージを送る仕組み」
です。
自動化と組み合わせると、例えばこんなことができます。
バッチが正常終了したら #batch-log に「成功しました」と投稿する。
エラーが起きたら #alert に「このバッチが落ちました」と通知する。
定期的な集計結果やレポートのサマリを、毎朝 Slack に流す。
つまり、「人間が見ている場所に、スクリプトから直接話しかける」感じです。
ここでは、初心者でも迷子にならないように
- Slack 通知の全体像(どこをどうつなぐのか)
- Incoming Webhook を使った一番シンプルな送り方
- 実務で使える「関数化」とエラー通知への組み込み
- セキュリティ・運用上の注意点(ここは少し深掘り)
を順にかみ砕いて話していきます。
全体像(Python → Slack の流れをざっくりつかむ)
Python は「HTTP で Slack にメッセージを投げる」
Slack にメッセージを送る仕組みはいくつかありますが、
初心者がまず覚えるべきは Incoming Webhook です。
イメージとしては、
Slack 側で「この URL に POST してくれたら、このチャンネルにメッセージ流すよ」という入り口(Webhook URL)を作る。
Python 側で、その URL に {"text": "こんにちは"} みたいな JSON を HTTP POST する。
たったこれだけです。
なので、やることは本質的に2つだけです。
Slack 側で Webhook URL を発行する(最初に1回だけの作業)。
Python から requests などを使って、その URL に JSON を POST する。
ここさえつながれば、「Python が Slack にしゃべる」準備は完了です。
Slack Incoming Webhook の基本イメージ(準備の話)
※実際のボタン操作はここでは細かく書きませんが、「何が手に入るのか」だけ押さえてください。
Slack のワークスペースで、管理画面から Incoming Webhook を設定すると、
https://hooks.slack.com/services/XXXXX/YYYYY/ZZZZZ…
のような長い URL が一つ発行されます。
この URL は、
「ここに JSON を POST したら、この URL に紐づいたチャンネルにメッセージを投稿する」
という「専用の入り口」です。
Python から見れば、
「決まった URL に HTTP POST するだけ」という、とても単純なターゲットになります。
この URL は「秘密」です。
誰でも知っていると、勝手にそのチャンネルに投稿できてしまうので、後でセキュリティのところで触れます。
まずは最小の Slack 通知コードを書いてみる
requests を使ったシンプルな送信
Python 側のコードとしては、こんな最小例で動きます。
import requests
SLACK_WEBHOOK_URL = "https://hooks.slack.com/services/XXXXX/YYYYY/ZZZZZ"
def send_slack_message(text: str):
payload = {"text": text}
resp = requests.post(SLACK_WEBHOOK_URL, json=payload, timeout=5)
resp.raise_for_status()
return resp
if __name__ == "__main__":
send_slack_message("Python から Slack に通知テストです。")
Pythonここで何が起きているかを一つずつ見ていきます。
SLACK_WEBHOOK_URL
Slack 側で発行した Incoming Webhook の URL を入れます。
今は直書きしていますが、実務では環境変数などから読み込むのがベターです。
payload = {"text": text}
Slack に送るメッセージを JSON にします。
最小限のフィールドは text だけです。ここに投稿したい本文を入れます。
requests.post(..., json=payload, timeout=5)
HTTP POST を投げています。json= を使うことで、自動的に JSON として送信されます。timeout=5 は「5秒以上かかったら諦める」というタイムアウトです。
自動化では、タイムアウトなしは危険なので必ず指定する癖をつけてください。
resp.raise_for_status()
Slack 側が 200 番以外(エラー)を返したときに例外を投げます。
通知に失敗したことをちゃんと捕まえられるようにするためです。
このコードを実行すると、指定した Slack チャンネルに一行メッセージが投稿されます。
自動化で使える形にする(関数化+エラー通知への組み込み)
バッチの「成功」と「失敗」でメッセージを分ける
単に「送れる」だけではなく、自動化バッチにきれいに組み込みたいので、
少し整理して関数を用意します。
import os
import logging
from pathlib import Path
import requests
BASE_DIR = Path(__file__).resolve().parent
LOG_FILE = BASE_DIR / "batch.log"
SLACK_WEBHOOK_URL = os.environ.get("SLACK_WEBHOOK_URL") # 環境変数から読む
def setup_logging():
logging.basicConfig(
filename=LOG_FILE,
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(name)s - %(message)s"
)
def send_slack(text: str):
if not SLACK_WEBHOOK_URL:
logging.warning("SLACK_WEBHOOK_URL が設定されていないため、Slack 通知をスキップします。")
return
payload = {"text": text}
try:
resp = requests.post(SLACK_WEBHOOK_URL, json=payload, timeout=5)
resp.raise_for_status()
except Exception as e:
logging.exception(f"Slack 通知の送信に失敗: {e}")
def main():
logging.info("日次バッチ開始")
# ここに実際の処理を書く
# 例: 1 / 0 でエラーをわざと起こす
logging.info("日次バッチ正常終了")
if __name__ == "__main__":
setup_logging()
try:
main()
send_slack("[OK] 日次バッチ正常終了")
except Exception:
logging.exception("日次バッチで予期せぬ例外")
send_slack("[ERROR] 日次バッチ異常終了。ログを確認してください。")
raise
Pythonこの構成は、自動化でかなり使える「定番パターン」です。
重要なポイントを少し深掘りします。
一つ目は、「Webhook URL を環境変数から読んでいる」ことです。
ソースコードにベタ書きすると、Git に上げたときに URL が漏洩する危険があります。
環境変数(や設定ファイル)から読み込むだけで、安全性がかなり上がります。
二つ目は、「Slack 通知自体のエラーも logging.exception で記録している」ことです。
通知機能もネットワークに依存するので、失敗することがあります。
そのときに、通知のせいで元のバッチのエラー原因が隠れないように、
通知関数の中で例外を握りつぶさず、ログに残しています(ただし元の例外は上で raise 済み)。
三つ目は、「成功時」と「失敗時」でメッセージを分けている」ことです。
Slack のタイムラインを見たときに、
緑(OK)と赤(ERROR)を見分けられるようにしておくと、運用が楽になります。
ここからさらに、絵文字やチャンネル名、環境名(dev / prod)などを盛り込むと、かなり実用的な通知になります。
メッセージの中身を設計する(何を書いておくと役に立つか)
「見た瞬間に分かる情報」と「ログを見るきっかけ」
Slack 通知の役割は、「詳細を全部伝える」ことではなく、
「何が起きたのかを一瞬で察して、必要ならログを見に行くきっかけを作る」
ことです。
なので、メッセージには最低限以下のような情報を含めると役立ちます。
どのバッチ(ジョブ名)。
どの環境(dev / staging / prod)。
いつ(日時)。
成功か失敗か。
例として、メッセージ組み立て関数を用意してみます。
from datetime import datetime
def build_success_message(batch_name: str, env: str = "prod") -> str:
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return f":white_check_mark: [{env}] {batch_name} 正常終了\n完了時刻: {now}"
def build_error_message(batch_name: str, env: str = "prod") -> str:
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return f":x: [{env}] {batch_name} 異常終了\n発生時刻: {now}\n詳細はログを確認してください。"
Pythonこれを使って、
if __name__ == "__main__":
setup_logging()
BATCH_NAME = "日次売上集計バッチ"
ENV = "prod"
try:
main()
send_slack(build_success_message(BATCH_NAME, ENV))
except Exception:
logging.exception("バッチで予期せぬ例外")
send_slack(build_error_message(BATCH_NAME, ENV))
raise
Pythonとすると、Slack を開いた瞬間に
どの環境の
どのバッチが
いつ成功(失敗)したのか
がひと目で分かります。
どこまで詳細を書くべきか
「エラーの詳細(スタックトレース)も全部 Slack に流したい」という欲求が出がちです。
ただ、これはあまりおすすめしません。
長いスタックトレースが Slack に流れると、
タイムラインがノイズだらけになる。
スマホでは読みづらい。
大事な他の通知を押し流してしまう。
など、運用上の負荷が大きくなります。
基本的には、
Slack には概要だけ(バッチ名・環境・時刻・成功/失敗)。
詳細はログファイル(logging)で確認する。
という役割分担にしておくと、きれいに回りやすいです。
少し進んだ話:通知の「頻度」と「しきい値」を考える
すべてのエラーで Slack 通知は NG
エラー通知のところでも話しましたが、
Slack 通知を「すべての小さなエラー」で飛ばすと、すぐに破綻します。
たとえば、
1つのバッチの中で 1000 件のファイルを処理していて、
そのうち 10 件だけちょっとしたフォーマットエラーでスキップした。
この 10 件それぞれで「エラー通知」を飛ばすのは、ほぼ確実にやりすぎです。
通知疲れが起きると、人はこうなります。
最初はちゃんと見る。
そのうち、「またか」で流し読み。
そのうち、「通知多すぎるからミュートしよう」。
そして、本当に重大な通知も見なくなる。
これを防ぐには、
致命的なエラー(バッチ全体が止まる)
→ 必ず Slack 通知。
軽微なエラー(レコード単位の失敗など)
→ ログには残すが Slack 通知はしない。
軽微なエラーでも、「件数がしきい値を超えたら」Slack 通知
→ 例えば「1回のバッチで 100件以上失敗したら Warning 通知」のようにする。
といったルールを設計します。
しきい値ベースの通知のイメージ
例えば、API のエラー件数に応じて通知するイメージです。
ERROR_THRESHOLD = 10
def run_batch():
error_count = 0
for uid in user_ids:
try:
fetch_user(uid)
except Exception:
logging.exception(f"ユーザー取得エラー: user_id={uid}")
error_count += 1
if error_count >= ERROR_THRESHOLD:
send_slack(f":warning: ユーザー取得エラー件数が多すぎます: {error_count}件")
Pythonこうすれば、
1〜2件の偶発的な失敗
→ ログだけ。
10件以上の異常な失敗増加
→ Slack に Warning 通知。
というように、「本当におかしい状況」だけを人間に投げることができます。
セキュリティと運用で気をつけるポイント
Webhook URL は「パスワード」と同じくらい大事に扱う
Slack の Incoming Webhook URL は、長いランダム文字列ですが、
これが漏れたら「誰でもそのチャンネルに投稿できる」状態になります。
なので、
ソースコードにベタ書きしない。
Git にコミットしない。
公開リポジトリに絶対置かない。
ことが重要です。
実務では、
環境変数(SLACK_WEBHOOK_URL)で渡す。
あるいは、Git 管理外の設定ファイル(.env など)で管理し、それを読み込む。
というパターンがよく使われます。
通知が「落ちても」本体のエラー原因が分かるようにする
Slack 通知自体も、ネットワークエラーや Slack 側の障害で失敗することがあります。
通知処理の中で例外が起きるときに、
通知のせいで元の例外が見えなくならないようにする
ことが大事です。
先ほどのように、
Slack 通知は best effort(できたらする)。
失敗しても logging.exception で記録だけしておき、元の例外の流れは壊さない。
という形にしておくと、本体のログで原因を追えるようになります。
まとめ(Slack 通知は「自動化と人間をつなぐ声帯」)
Python 自動化における Slack 通知の役割を整理すると、こうなります。
Slack 通知は「コードから直接チャンネルに話しかける」手段で、特にエラー通知やバッチ完了報告と相性がいい。
Incoming Webhook を使えば、「決まった URL に JSON を POST するだけ」でメッセージを送れる。
通知関数(send_slack)を用意し、トップレベルの try/except の中で「成功時」と「失敗時」に呼び分けると、自動化バッチにきれいに組み込める。
メッセージには「バッチ名・環境・時刻・成功/失敗」を含め、詳細はログに任せることで、Slack は“気づき”に専念させる。
Webhook URL や認証情報は環境変数などで管理し、通知の頻度と範囲(どのエラーで通知するか)を決めることで、通知疲れを防ぐ。
ここまで押さえれば、「Python のバッチが自分に Slack で話しかけてくる」状態はいつでも作れます。
