監視ツールのCLIコマンドを実装していたとき、妙な挙動に遭遇しました。
Jenkinsでpython -m monitoring_sdk.core.cli metabase-checkを実行すると、エラーも出ず、終了コード0で正常終了する。でも、実行されるはずの処理が何も動いていない。レポートファイルも生成されない。
+ python -m monitoring_sdk.core.cli metabase-check --config config.yaml --output reports
+ echo === チェック完了 ===
=== チェック完了 ===
+ ls -la reports/
total 0
drwxr-xr-x. 2 root root 40 Jan 28 02:23 .
正常終了しているのに、何も起きていない。この「静かな失敗」に1時間以上悩まされました。
正直、こんな初歩的な問題にハマるとは思っていませんでした。
関連書籍(学習用)
実例で出てきたPythonの基本や実行周りを理解するのに強力なのがこちら:
[📦 商品リンク: moshimo-card-EdE1y]
『みんなのPython 第5版』では、Pythonの基礎からモジュール設計・実行方法まで丁寧に解説されています。CLI周りの落とし穴を未然に防げます。
AI活用の前提となるPython基礎を固めたい方にもおすすめです。
AI駆動開発のスピード感と脆さ
このプロジェクトは、AIを使ってかなりのスピードで開発していました。CLIコマンドの実装、ログ設定、監視ロジック、レポート生成。コード自体はどんどん書けます。
でも、振り返ってみると、きちんとレビューをしないで「動くだろう」という前提でコードを書き続けていました。テストは後回し。実際に動かしてみるのは最後の最後。
そして、テスト段階でこの問題にぶつかりました。
コーディング自体のスピードは確かに速い。でも、こういうトラブルにハマると意外と脆い。原因が分からず、ログを追いかけ、仮説を立て、検証を繰り返す。気づけば1時間以上経っていました。
最初の仮説:ログ出力の問題?
最初はPythonの標準出力バッファリングを疑いました。Jenkinsfileにpython -uフラグを追加してバッファリングを無効化しようとしましたが、「それよりPython側のログ出力を強化したほうがいいのでは?」と気づき、方向転換。
各モジュールにロガーを追加し、処理の各段階でINFOログを出すようにしました。
from monitoring_sdk.utils.logging_config import get_logger
logger = get_logger(__name__)
def metabase_check(config: str, output: str):
logger.info("metabase-checkコマンドを開始します: config=%s, output=%s", config, output)
# ... 処理 ...
logger.info("metabase-checkコマンドが完了しました")
※ここからは開発体験の話になります。
ログ出力を追加することにしましたが、対象は32ファイル。monitors、CLI commands、reporters、HTTP API関連のファイル全てです。
手作業でやっていたら、半日はかかる作業です。ファイルを開いて、インポート文を追加して、各関数にログを追加して、動作確認して...を32回繰り返す。
でも、今回は違いました。私が開発しているDevLoop Runnerを使ったからです。これは、issueを書いたら自動でPRまで持っていってくれるツールです。
issue: 「monitoring_sdk内の全32ファイルにget_loggerを使ったログ出力を追加」
↓
自動でコード修正(約2時間)
↓
PR作成
実際にかかった時間は2時間ほど。でも、私が手を動かしたのはissue作成とジョブ実行の3〜5分だけです。残りの2時間は、自動処理が走っている間に他の作業ができます。
手作業なら半日べったり作業に張り付くところが、実質的な拘束時間は5分で済む。この差は大きいです。
32ファイル分のログ追加が完了し、マージ。デバッグログも充実しました。
デバッグログで見えた不自然な挙動
ログレベルをDEBUGに上げて再実行。すると、こんな出力が:
2026-01-28 09:01:37,029 - monitoring_sdk.core - DEBUG - monitoring_sdk.core パッケージを初期化しました
2026-01-28 09:01:37,066 - monitoring_sdk.monitors - DEBUG - monitoring_sdk.monitors パッケージを初期化しました
2026-01-28 09:01:37,518 - monitoring_sdk.cloud - DEBUG - monitoring_sdk.cloud パッケージを初期化しました
+ echo === チェック完了 ===
パッケージの__init__.pyが実行されている証拠はある。でも、metabase_check関数内のログが一切出ない。"metabase-checkコマンドを開始します"というログが出ていない。
結論から言うと、main()関数が一度も呼ばれていませんでした。
終了コード0の罠
念のため終了コードを明示的に確認してみました。
+ set +e
+ python -m monitoring_sdk.core.cli metabase-check --config config.yaml --output reports
+ EXIT_CODE=$?
+ echo "終了コード: $EXIT_CODE"
終了コード: 0
やはり0。エラーではない。じゃあ何が起きているのか?
さらに--helpを試してみました。
+ python -m monitoring_sdk.core.cli --help
+ echo "ヘルプ表示完了"
ヘルプ表示完了
ヘルプの内容が何も出力されない。コマンドは実行されている(+記号が表示されている)のに、出力が完全に空。
これは、python -mでモジュールを実行しても、エントリーポイントが正しく設定されていない状態でした。
原因特定:エントリーポイントの欠如
cli.pyの実装を見直しました。
# monitoring_sdk/core/cli.py
import click
@click.group()
def main():
"""監視SDKのCLIエントリーポイント"""
pass
@main.command()
@click.option("--config", required=True)
@click.option("--output", default="reports")
def metabase_check(config: str, output: str):
# ... 実装 ...
pass
一見問題なさそうです。でも、ファイルの最後を見ると:
# ここで終わり。if __name__ == "__main__": がない
これが原因でした。
python -m monitoring_sdk.core.cliでモジュールを実行すると:
- Pythonは
monitoring_sdk/core/cli.pyをインポートする - モジュールレベルのコード(import文、関数定義、デコレータ)は実行される
- でも
main()関数は呼ばれない - 何もせずに終了コード0で終了
正直、AIが作ったコードだから「ちゃんと実装されているだろう」と思い込んでいました。だから、そもそもエントリーポイントの有無なんて確認すらしていませんでした。
ここで詰まったのは痛かったです。
Pythonのエントリーポイントについてのおさらい
せっかくなので、Pythonのモジュール実行とエントリーポイントについて整理しておきます。
python -mの挙動
python -m module.pathを実行すると、Pythonは以下の順序でエントリーポイントを探します:
module/path/__main__.pyがあれば実行- なければ
module/path.pyを実行(ただしif __name__ == "__main__"が必要)
重要なのは、モジュールをインポートはするが、自動でmain()を呼んでくれるわけではないという点です。
エントリーポイントの2つの方法
| 実行方法 | 必要なファイル/コード | 用途 |
|---|---|---|
python -m module.path |
__main__.py |
パッケージとして配布 |
python script.py |
if __name__ == "__main__" |
スクリプトとして実行 |
どちらにも対応する場合:
両方実装しておくのが無難です。今回はこの両方が欠けていました。
実装例
# monitoring_sdk/core/__main__.py
from monitoring_sdk.core.cli import main
if __name__ == "__main__":
main()
# monitoring_sdk/core/cli.py(最後に追加)
if __name__ == "__main__":
main()
これで、どちらの起動経路でもmain()が呼ばれるようになります。
修正後の動作
2026-01-28 09:49:07,417 - monitoring_sdk.monitors.metabase_monitor - INFO - カードチェックを開始します
2026-01-28 09:49:07,417 - monitoring_sdk.monitors.metabase_monitor - INFO - カードチェックが完了しました: status=OK
2026-01-28 09:49:07,417 - monitoring_sdk.monitors.metabase_monitor - INFO - Metabaseレポート生成が完了しました: file=reports/summary.md
2026-01-28 09:49:07,418 - monitoring_sdk.cli.commands.metabase_check - INFO - metabase-checkコマンドが完了しました: status=OK
期待通りの動作になりました。
学んだこと:「アクセルとブレーキ」の感覚
AI開発全体を俯瞰するなら
AI駆動開発を加速するだけでなく、「どこでアクセルを踏みどこでブレーキを踏むか」を体系的に学ぶならこちらもおすすめです:
[📦 商品リンク: moshimo-card-HD5Yl]
『AI駆動開発入門』では、AIを活かした開発プロセスの設計・実践・評価までを解説。単なるコード生成に留まらない思考法が身につきます。
1. 自動化のおかげで拘束時間は劇的に短縮
issueからPRまでの自動化があれば、32ファイルのログ追加も手作業は3〜5分で終わります。実際の処理に2時間かかりますが、その間は他の作業ができます。
手作業なら半日べったり作業に張り付く必要があるところが、実質的な拘束時間は5分で済む。この差は大きいです。
2. でも「AIが作ったから大丈夫」という過信は危険
「ちゃんと実装されているだろう」という思い込みで、基本的な部分の確認を怠りました。
エントリーポイントの有無なんて、手書きなら絶対に確認するポイントです。でも、AIに任せていると、そもそも意識すらしなくなる。
3. silent failureは気づきにくい
エラーも出ず、終了コード0で正常終了。でも何も動いていない。こういう「静かな失敗」は、ログが充実していないと原因特定に時間がかかります。
今回はデバッグログのおかげで「パッケージ初期化は動いている」「でも関数は呼ばれていない」という状況が見えました。
4. アクセルを踏むところ、ブレーキを踏むところ
アクセルを踏むところ(AI駆動でスピード重視):
- 定型的なコード生成(ログ出力、エラーハンドリング)
- 既存パターンの適用(設定ファイル、テストケース)
- リファクタリング(コードの整理、命名の統一)
ブレーキを踏むところ(丁寧に確認):
- エントリーポイント・起動経路の設計
- 依存関係の整理(インポート、パッケージ構造)
- 最初のテスト実行(期待通り動くか)
意外とここが肝だったりします。
まとめ
AI駆動開発は確実に速い。でも、「AIが作ったから大丈夫」という過信でレビューを省略すると意外と脆い。
大事なのは、どこでアクセルを踏み、どこでブレーキを踏むかの感覚を磨くことです。
今回の問題は初歩的でしたが、こういう初歩的な問題こそ、最初のテスト段階で丁寧に確認すべきでした。「動くだろう」ではなく、「本当に動くか」を確認する。そのバランス感覚が、AI駆動開発では特に重要だと実感しました。