17.4。 信号 —非同期イベントのハンドラーを設定します
このモジュールは、Pythonでシグナルハンドラーを使用するメカニズムを提供します。 シグナルとそのハンドラーを操作するためのいくつかの一般的なルール:
- 特定のシグナルのハンドラーは、一度設定されると、明示的にリセットされるまでインストールされたままになります(Pythonは、基になる実装に関係なくBSDスタイルのインターフェイスをエミュレートします)。ただし、基になる実装に続く
SIGCHLD
のハンドラーは例外です。 。 - クリティカルセクションからの信号を一時的に「ブロック」する方法はありません(これはすべてのUnixフレーバーでサポートされているわけではないため)。
- Pythonシグナルハンドラーは、Pythonユーザーに関する限り非同期で呼び出されますが、Pythonインタープリターの「アトミック」命令間でのみ発生する可能性があります。 これは、純粋にCで実装された長い計算中に到着する信号(大量のテキストでの正規表現の一致など)が任意の時間遅延する可能性があることを意味します。
- I / O操作中にシグナルが到着すると、シグナルハンドラが戻った後にI / O操作で例外が発生する可能性があります。 これは、中断されたシステムコールに関する基礎となるUnixシステムのセマンティクスに依存します。
- Cシグナルハンドラーは常に戻るため、
SIGFPE
やSIGSEGV
のような同期エラーをキャッチすることはほとんど意味がありません。 - Pythonは、デフォルトで少数のシグナルハンドラーをインストールします。
SIGPIPE
は無視され(したがって、パイプとソケットの書き込みエラーは通常のPython例外として報告されます)、SIGINT
は [に変換されます。 X207X]例外。 これらはすべてオーバーライドできます。 - シグナルとスレッドの両方が同じプログラムで使用される場合は、注意が必要です。 シグナルとスレッドを同時に使用する際に覚えておくべき基本的なことは、実行のメインスレッドで常に signal()操作を実行することです。 どのスレッドでも alarm()、 getsignal()、 pause()、 setitimer()、または getitimer( ); 新しいシグナルハンドラーを設定できるのはメインスレッドのみであり、シグナルを受信するのはメインスレッドだけです(これは、基になるスレッド実装が個々のスレッドへのシグナルの送信をサポートしている場合でも、Python signal モジュールによって強制されます)スレッド)。 これは、シグナルをスレッド間通信の手段として使用できないことを意味します。 代わりにロックを使用してください。
signal モジュールで定義されている変数は次のとおりです。
- signal.SIG_DFL
- これは、2つの標準的な信号処理オプションの1つです。 シグナルのデフォルト機能を実行するだけです。 たとえば、ほとんどのシステムでは、
SIGQUIT
のデフォルトのアクションはコアをダンプして終了することですが、SIGCHLD
のデフォルトのアクションは単にそれを無視することです。
- signal.SIG_IGN
- これは別の標準的なシグナルハンドラーであり、指定されたシグナルを単に無視します。
- SIG*
- すべての信号番号はシンボリックに定義されています。 たとえば、ハングアップ信号は
signal.SIGHUP
として定義されます。 変数名は、<signal.h>
にあるように、Cプログラムで使用される名前と同じです。 'signal()
'のUnixマニュアルページには、既存のシグナルがリストされています(一部のシステムでは、これは signal(2)であり、他のシステムでは、リストは signal(7)にあります。 )。 すべてのシステムが同じ信号名のセットを定義しているわけではないことに注意してください。 システムによって定義された名前のみがこのモジュールによって定義されます。
- signal.CTRL_C_EVENT
Ctrl + C キーストロークイベントに対応する信号。 この信号は、 os.kill()でのみ使用できます。
可用性:Windows。
バージョン2.7の新機能。
- signal.CTRL_BREAK_EVENT
Ctrl + Break キーストロークイベントに対応する信号。 この信号は、 os.kill()でのみ使用できます。
可用性:Windows。
バージョン2.7の新機能。
- signal.NSIG
- 最高信号番号の番号より1つ多い。
- signal.ITIMER_REAL
- インターバルタイマーをリアルタイムでデクリメントし、満了時に
SIGALRM
を配信します。
- signal.ITIMER_VIRTUAL
- プロセスの実行時にのみインターバルタイマーをデクリメントし、満了時にSIGVTALRMを配信します。
- signal.ITIMER_PROF
- プロセスの実行時とシステムがプロセスに代わって実行しているときの両方で、インターバルタイマーをデクリメントします。 ITIMER_VIRTUALと組み合わせて、このタイマーは通常、ユーザーおよびカーネル空間でアプリケーションが費やした時間をプロファイリングするために使用されます。 SIGPROFは有効期限が切れると配信されます。
signal モジュールは、1つの例外を定義します。
- exception signal.ItimerError
- 基になる setitimer()または getitimer()実装からのエラーを通知するために発生します。 無効なインターバルタイマーまたは負の時間が setitimer()に渡された場合、このエラーが発生する可能性があります。 このエラーは
IOError
のサブタイプです。
signal モジュールは、次の機能を定義します。
- signal.alarm(time)
- time がゼロ以外の場合、この関数は
SIGALRM
信号が time 秒でプロセスに送信されることを要求します。 以前にスケジュールされたアラームはキャンセルされます(一度にスケジュールできるアラームは1つだけです)。 戻り値は、以前に設定されたアラームが配信されるまでの秒数です。 time がゼロの場合、アラームはスケジュールされず、スケジュールされたアラームはキャンセルされます。 戻り値がゼロの場合、現在アラームはスケジュールされていません。 (Unixのマニュアルページ alarm(2)を参照してください。)可用性:Unix。
- signal.getsignal(signalnum)
- シグナル signalnum の現在のシグナルハンドラーを返します。 戻り値は、呼び出し可能なPythonオブジェクト、または特別な値 signal.SIG_IGN 、 signal.SIG_DFL 、または None のいずれかです。 ここで、 signal.SIG_IGN は信号が以前に無視されたことを意味し、 signal.SIG_DFL は信号を処理するデフォルトの方法が以前に使用されていたことを意味し、
None
は以前のシグナルハンドラーがPythonからインストールされていないこと。
- signal.pause()
- シグナルが受信されるまでプロセスをスリープ状態にします。 次に、適切なハンドラーが呼び出されます。 何も返しません。 Windowsではありません。 (Unixのマニュアルページ signal(2)を参照してください。)
- signal.setitimer(which, seconds[, interval])
で指定されたインターバルタイマー( signal.ITIMER_REAL 、 signal.ITIMER_VIRTUAL 、 signal.ITIMER_PROF のいずれか)をで指定しての後に起動するように設定します。 X168X]秒(フロートが受け入れられ、 alarm()とは異なります)、その後は間隔秒ごと。 で指定されたインターバルタイマーは、秒をゼロに設定することでクリアできます。
インターバルタイマーが作動すると、信号がプロセスに送信されます。 送信される信号は、使用されているタイマーによって異なります。 signal.ITIMER_REAL は
SIGALRM
を配信し、 signal.ITIMER_VIRTUAL はSIGVTALRM
を送信し、 signal.ITIMER_PROF はSIGPROF
。古い値はタプルとして返されます:(遅延、間隔)。
無効なインターバルタイマーを通過させようとすると、 ItimerError が発生します。 可用性:Unix。
バージョン2.6の新機能。
- signal.getitimer(which)
which で指定されたインターバルタイマーの現在値を返します。 可用性:Unix。
バージョン2.6の新機能。
- signal.set_wakeup_fd(fd)
ウェイクアップfdを fd に設定します。 信号を受信すると、
'\0'
バイトがfdに書き込まれます。 これをライブラリで使用して、ポーリングまたは選択呼び出しをウェイクアップし、信号を完全に処理できるようにすることができます。古いウェイクアップfdが返されます(またはファイル記述子ウェイクアップが有効になっていない場合は-1)。 fd が-1の場合、ファイル記述子のウェイクアップは無効になります。 -1でない場合、 fd は非ブロッキングである必要があります。 ポーリングを呼び出す前、または再度選択する前に、 fd からバイトを削除するのはライブラリの責任です。
スレッドが有効になっている場合、この関数はメインスレッドからのみ呼び出すことができます。 他のスレッドから呼び出そうとすると、
ValueError
例外が発生します。バージョン2.6の新機能。
- signal.siginterrupt(signalnum, flag)
システムコールの再起動動作の変更:フラグが False の場合、シグナル signalnum によって中断されるとシステムコールが再開されます。それ以外の場合、システムコールは中断されます。 何も返しません。 可用性:Unix(詳細については、manページ siginterrupt(3)を参照してください)。
signal()を使用してシグナルハンドラーをインストールすると、指定されたシグナルの真のフラグ値を使用して
siginterrupt()
を暗黙的に呼び出すことにより、再起動動作が割り込み可能にリセットされることに注意してください。バージョン2.6の新機能。
- signal.signal(signalnum, handler)
シグナル signalnum のハンドラーを関数 handler に設定します。 handler は、2つの引数(以下を参照)をとる呼び出し可能なPythonオブジェクト、または特別な値 signal.SIG_IGN または signal.SIG_DFL のいずれかです。 以前のシグナルハンドラーが返されます(上記の getsignal()の説明を参照してください)。 (Unixのマニュアルページ signal(2)を参照してください。)
スレッドが有効になっている場合、この関数はメインスレッドからのみ呼び出すことができます。 他のスレッドから呼び出そうとすると、
ValueError
例外が発生します。ハンドラーは、信号番号と現在のスタックフレーム(
None
またはフレームオブジェクト。フレームオブジェクトの説明については、タイプのの説明を参照)の2つの引数で呼び出されます。階層または inspect モジュールの属性の説明を参照してください)。Windowsでは、 signal()は、
SIGABRT
、SIGFPE
、SIGILL
、SIGINT
、 [X102Xでのみ呼び出すことができます。 ]、またはSIGTERM
。 それ以外の場合は、ValueError
が発生します。
17.4.1。 例
これが最小限のサンプルプログラムです。 alarm()関数を使用して、ファイルを開くのを待つ時間を制限します。 これは、ファイルがオンになっていない可能性のあるシリアルデバイス用である場合に役立ちます。これにより、通常、 os.open()が無期限にハングします。 解決策は、ファイルを開く前に5秒のアラームを設定することです。 操作に時間がかかりすぎると、アラーム信号が送信され、ハンドラーが例外を発生させます。
import signal, os
def handler(signum, frame):
print 'Signal handler called with signal', signum
raise IOError("Couldn't open device!")
# Set the signal handler and a 5-second alarm
signal.signal(signal.SIGALRM, handler)
signal.alarm(5)
# This open() may hang indefinitely
fd = os.open('/dev/ttyS0', os.O_RDWR)
signal.alarm(0) # Disable the alarm