.. ============================================================ signal -- Receive notification of asynchronous system events ============================================================ ================================================ signal -- 非同期のシステムイベント通知を受け取る ================================================ .. :synopsis: Receive notification of asynchronous system events .. module:: signal :synopsis: 非同期のシステムイベント通知を受け取る .. :Purpose: Receive notification of asynchronous system events :Available In: 1.4 and later :目的: 非同期のシステムイベント通知を受け取る :利用できるバージョン: 1.4 以上 .. Programming with Unix signal handlers is a non-trivial endeavor. This is an introduction, and does not include all of the details you may need to use signals successfully on every platform. There is some degree of standardization across versions of Unix, but there is also some variation, so consult documentation for your OS if you run into trouble. .. note:: Unix シグナルハンドラでプログラミングすることは普通以上の努力が必要です。本稿はシグナルの入門です。全てのプラットホーム上で正しくシグナルを利用することの詳細は説明していません。Unix のバージョンを横断して標準仕様があり、また変形した仕様もあります。そのため、実行して問題があれば使用中の OS のドキュメントを調べてください。 .. Signals are an operating system feature that provide a means of notifying your program of an event, and having it handled asynchronously. They can be generated by the system itself, or sent from one process to another. Since signals interrupt the regular flow of your program, it is possible that some operations (especially I/O) may produce error if a signal is received in the middle. シグナルはあるイベントをプログラムへ通知するオペレーティングシステムの機能で、非同期にその通知を受け取ります。シグナルはそのシステムが生成するか、1つのプロセスから他のプロセスへ送信されます。シグナルはプログラムの通常処理の流れを中断させるので、シグナルを受信したら何らかの操作(特に I/O)でエラーを発生させることができます。 .. Signals are identified by integers and are defined in the operating system C headers. Python exposes the signals appropriate for the platform as symbols in the :mod:`signal` module. For the examples below, I will use ``SIGINT`` and ``SIGUSR1``. Both are typically defined for all Unix and Unix-like systems. シグナルは整数値で識別され、オペレーティングシステムの C 言語のヘッダに定義されています。Python は :mod:`signal` モジュールのシンボルとしてプラットホームに適したシグナルを定義します。 ``SIGINT`` と ``SIGUSR1`` を使用する例を次に示します。両方とも全ての Unix や Unix に似たシステムで定義されています。 .. Receiving Signals ================= シグナルを受け取る ================== .. As with other forms of event-based programming, signals are received by establishing a callback function, called a *signal handler*, that is invoked when the signal occurs. The arguments to your signal handler are the signal number and the stack frame from the point in your program that was interrupted by the signal. イベントベースプログラミングの別の形態として、あるシグナルが発生したときに実行される *シグナルハンドラ* というコールバック関数を設定することでそのシグナルを受け取れます。シグナルハンドラへの引数はシグナル番号とシグナルによって中断されたプログラム位置のスタックフレームです。 .. include:: signal_signal.py :literal: :start-after: #end_pymotw_header .. This relatively simple example script loops indefinitely, pausing for a few seconds each time. When a signal comes in, the sleep call is interrupted and the signal handler ``receive_signal()`` prints the signal number. When the signal handler returns, the loop continues. この例は数秒毎に停止しながら無限ループする比較的シンプルなものです。シグナルが発生したとき sleep 呼び出しは中断されて、シグナルハンドラ ``receive_signal()`` がシグナル番号を表示します。シグナルハンドラが返される場合、ループは継続します。 .. To send signals to the running program, I use the command line program kill. To produce the output below, I ran ``signal_signal.py`` in one window, then ``kill -USR1 $pid``, ``kill -USR2 $pid``, and ``kill -INT $pid`` in another. 実行中のプログラムへシグナルを送信するために kill コマンドを使用します。次の出力を生成するために1つのウィンドウで ``signal_signal.py`` を実行しました。その後、別のウィンドウで ``kill -USR1 $pid`` , ``kill -USR2 $pid`` , ``kill -INT $pid`` を実行しました。 :: $ python signal_signal.py My PID is: 71387 Waiting... Waiting... Waiting... Received: 30 Waiting... Waiting... Received: 31 Waiting... Waiting... Traceback (most recent call last): File "signal_signal.py", line 25, in time.sleep(3) KeyboardInterrupt getsignal() =========== .. To see what signal handlers are registered for a signal, use :func:`getsignal()`. Pass the signal number as argument. The return value is the registered handler, or one of the special values ``signal.SIG_IGN`` (if the signal is being ignored), ``signal.SIG_DFL`` (if the default behavior is being used), or ``None`` (if the existing signal handler was registered from C, rather than Python). あるシグナルに登録されているシグナルハンドラを確認するには :func:`getsignal()` を使用してください。そして、引数にシグナル番号を渡してください。返り値は登録されたハンドラか、 ``signal.SIG_IGN`` (シグナルが無視された場合), ``signal.SIG_DFL`` (デフォルト動作が用いられた)の特殊な値のどれかか、又は None (存在するシグナルハンドラが Python ではなく C で登録されていた場合)です。 .. include:: signal_getsignal.py :literal: :start-after: #end_pymotw_header .. Again, since each OS may have different signals defined, the output you see from running this on other systems may vary. This is from OS X: 大事なことなので2回言いますが、それぞれの OS は違ったシグナルを定義しているかもしれないので、他のシステムでこのサンプルコードを実行すると出力結果は変わるかもしれません。次の実行結果は OS X のものです。 :: $ python signal_getsignal.py SIGHUP ( 1): SIG_DFL SIGINT ( 2): <built-in function default_int_handler> SIGQUIT ( 3): SIG_DFL SIGILL ( 4): SIG_DFL SIGTRAP ( 5): SIG_DFL SIGIOT ( 6): SIG_DFL SIGEMT ( 7): SIG_DFL SIGFPE ( 8): SIG_DFL SIGKILL ( 9): None SIGBUS (10): SIG_DFL SIGSEGV (11): SIG_DFL SIGSYS (12): SIG_DFL SIGPIPE (13): SIG_IGN SIGALRM (14): <function alarm_received at 0x7c3f0> SIGTERM (15): SIG_DFL SIGURG (16): SIG_DFL SIGSTOP (17): None SIGTSTP (18): SIG_DFL SIGCONT (19): SIG_DFL SIGCHLD (20): SIG_DFL SIGTTIN (21): SIG_DFL SIGTTOU (22): SIG_DFL SIGIO (23): SIG_DFL SIGXCPU (24): SIG_DFL SIGXFSZ (25): SIG_IGN SIGVTALRM (26): SIG_DFL SIGPROF (27): SIG_DFL SIGWINCH (28): SIG_DFL SIGINFO (29): SIG_DFL SIGUSR1 (30): SIG_DFL SIGUSR2 (31): SIG_DFL .. Sending Signals =============== シグナルを送る ============== .. The function for sending signals is ``os.kill()``. Its use is covered in the section on the :mod:`os` module, :ref:`creating-processes-with-os-fork`. シグナルを送るための関数は ``os.kill()`` です。その使用方法は PyMOTW の :mod:`os` モジュール や :ref:`creating-processes-with-os-fork` で説明しています。 .. Alarms ====== アラーム ======== .. Alarms are a special sort of signal, where your program asks the OS to notify it after some period of time has elapsed. As `the standard module documentation for os `_ points out, this is useful for avoiding blocking indefinitely on an I/O operation or other system call. アラームは一定時間が経過した後にプログラムがそのことを通知するために OS へ依頼する特殊なシグナルの種類です。 `os の標準モジュールドキュメント `_ によると、I/O 操作や他のシステムコールが永久にブロッキングしないようにするために役に立ちます。 .. include:: signal_alarm.py :literal: :start-after: #end_pymotw_header .. In this example, the call to :func:`sleep()` does not last the full 4 seconds. この例では :func:`sleep()` の呼び出しは4秒間継続されません。 :: $ python signal_alarm.py Before: Sun Aug 17 10:51:09 2008 Alarm : Sun Aug 17 10:51:11 2008 After : Sun Aug 17 10:51:11 2008 .. Ignoring Signals ================ シグナルを無視する ================== .. To ignore a signal, register ``SIG_IGN`` as the handler. This script replaces the default handler for ``SIGINT`` with ``SIG_IGN``, and registers a handler for ``SIGUSR1``. Then it uses :func:`signal.pause()` to wait for a signal to be received. シグナルを無視するためにはハンドラとして ``SIG_IGN`` を登録します。このスクリプトは ``SIGINT`` のデフォルトハンドラを ``SIG_IGN`` で置き換えて ``SIGUSR1`` のために登録します。その後、受け取るシグナルを待つために :func:`signal.pause()` を使用します。 .. include:: signal_ignore.py :literal: :start-after: #end_pymotw_header .. Normally ``SIGINT`` (the signal sent by the shell to your program when you hit Ctrl-C) raises a :ref:`KeyboardInterrupt `. In this example, we ignore ``SIGINT`` and raise :ref:`SystemExit ` when we see ``SIGUSR1``. Each ``^C`` represents an attempt to use Ctrl-C to kill the script from the terminal. Using ``kill -USR1 72598`` from another terminal eventually causes the script to exit. 通常では ``SIGINT`` (Ctrl-C を入力したとき、シェルからプログラムへ送信されるシグナル)は :ref:`KeyboardInterrupt ` を発生させます。この例では ``SIGINT`` を無視して ``SIGUSR1`` を受け取ったときに :ref:`SystemExit ` を発生させます。 ``^C`` はターミナルからそのスクリプトを終了させようと Ctrl-C を入力したことを表しています。 ``kill -USR1 72598`` を他のターミナルから実行することで最終的にそのスクリプトを終了させます。 :: $ python signal_ignore.py My PID: 72598 ^C^C^C^CExiting .. Signals and Threads =================== シグナルとスレッド ================== .. Signals and threads don't generally mix well because only the main thread of a process will receive signals. The following example sets up a signal handler, waits for the signal in one thread, and sends the signal from another. シグナルとスレッドを同時に使用することは一般的にうまくいきません。1つのプロセスのメインスレッドのみがシグナルを受け取るからです。次の例では、1つのスレッドでシグナルを待つシグナルハンドラをセットします。そして、他の一方からシグナルを送ります。 .. include:: signal_threads.py :literal: :start-after: #end_pymotw_header .. Notice that the signal handlers were all registered in the main thread. This is a requirement of the signal module implementation for Python, regardless of underlying platform support for mixing threads and signals. Although the receiver thread calls :func:`signal.pause()`, it does not receive the signal. The ``signal.alarm(2)`` call near the end of the example prevents an infinite block, since the receiver thread will never exit. 複数のシグナルハンドラがメインスレッドで全て登録されていることに注意してください。これはスレッドとシグナルを同時に使用するために根本となるプラットホームの機能に関係なく、Python の signal モジュール実装の必須条件です。receiver スレッドは :func:`signal.pause()` を呼び出しますが、そのスレッドはシグナルを受け取りません。receiver スレッドは決して終了しないので永久にブロッキングしないようにサンプルコードの最後付近で ``signal.alarm(2)`` を呼び出します。 :: $ python signal_threads.py Waiting for signal in Sending signal in Received signal 30 in <_MainThread(MainThread, started)> Waiting for Alarm clock .. Although alarms can be set in threads, they are also received by the main thread. アラームはスレッドの中でセットされていますが、そのシグナルもまたメインスレッドで受け取られます。 .. include:: signal_threads_alarm.py :literal: :start-after: #end_pymotw_header .. Notice that the alarm does not abort the :func:`sleep()` call in :func:`use_alarm()`. そのアラームは :func:`use_alarm()` の :func:`sleep()` 呼び出しを中断させないことに注意してください。 :: $ python signal_threads_alarm.py Sun Aug 17 12:06:00 2008 Setting alarm in Sun Aug 17 12:06:00 2008 Sleeping in Sun Aug 17 12:06:00 2008 Waiting for ; Sun Aug 17 12:06:03 2008 Done with sleep Sun Aug 17 12:06:03 2008 Alarm in <_MainThread(MainThread, started)> Sun Aug 17 12:06:03 2008 Exiting normally .. `signal `_ Standard library documentation for this module. :ref:`creating-processes-with-os-fork` The :func:`kill()` function can be used to send signals between processes. .. seealso:: `signal `_ 本モジュールの標準ライブラリドキュメント :ref:`creating-processes-with-os-fork` :func:`kill()` 関数はプロセス間でシグナルを送るために使用されます。