SIGINTのキャプチャと終了処理
Python
プログラムをCtrl+C
で中断するとき、SIGINT
(シグナル番号2)が送信されます。これをキャプチャして適切に終了処理を行うためには、“signalモジュール
を使用します。
基本的なシグナルハンドラの実装
signal
モジュールを使って、SIGINT
をキャプチャし、Gracefulにプログラムを終了させる例を紹介します。
import signal
import sys
def signal_handler(sig, frame):
print('You pressed Ctrl+C!')
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
print('Press Ctrl+C to exit')
signal.pause()
signal.signal()
でSIGINT
を指定し、キャプチャ後にsys.exit(0)
で安全に終了します。
KeyboardInterrupt
との違い
Ctrl+C
をキャプチャする方法としては、KeyboardInterrupt
を使うこともできますが、signal.signal()
を使うと、kill -SIGINT
コマンドや他のシグナル送信方法にも対応できます。
try:
while True:
# 長時間のタスク
pass
except KeyboardInterrupt:
print("Graceful shutdown...")
KeyboardInterrupt
は特定の例外処理で簡単に扱えますが、シグナルハンドラを使うと、プログラム全体での一貫した制御が可能です。
コンテキストマネージャによるシグナルハンドリング
複雑なケースでは、コンテキストマネージャを使ってシグナルハンドリングを簡潔にすることもできます。次の例では、GracefulInterruptHandler
というクラスを定義し、複数のシグナルを管理します。
import signal
from contextlib import contextmanager
class GracefulInterruptHandler:
def __init__(self):
self.interrupted = False
def __enter__(self):
self.old_handler = signal.getsignal(signal.SIGINT)
signal.signal(signal.SIGINT, self.handler)
return self
def handler(self, signum, frame):
self.interrupted = True
def __exit__(self, exc_type, exc_val, exc_tb):
signal.signal(signal.SIGINT, self.old_handler)
with GracefulInterruptHandler() as h:
while not h.interrupted:
print("Running...")
このようにして、Ctrl+C
が押されたときにGracefulにプログラムを終了させることができます。
まとめ
Python
でSIGINT
をキャプチャするには、signal.signal()
を使う方法が便利です。特に複数のシグナルやカスタム処理を扱いたい場合、シグナルハンドラを使用することで柔軟なプログラムが実現できます。また、シンプルなケースではKeyboardInterrupt
でも対応可能です。