5

私は最近 python を使い始めました。この動作に遭遇したとき、キーボード割り込みの処理で遊んでいました

import signal,sys

def handleInt(sign,no):
    print "interrupted"

signal.signal(signal.SIGINT,handleInt)    # exception raised is IOError

try:
    sys.stdin.read(1)
except IOError:
    print "io interrupt"

しかし、信号処理をtry-exceptの後に変更すると

import signal,sys

def handleInt(sign,no):
    print "interrupted"

try:
    sys.stdin.read(1)
except KeyboardInterrupt:
    print "keyboard interrupt"

signal.signal(signal.SIGINT,handleInt)    # exception raised is KeyboardInterrupt

ctrl+c を押すと、2つのケースで例外に違いがあります.では、なぜこの動作なのですか?

4

2 に答える 2

5

Python には、 用の独自のビルトイン シグナル ハンドラがありSIGINTます。このハンドラは単純に を発生させKeyboardInterruptます。最初のコードでは、組み込みハンドラーを新しいハンドラーに置き換えたため、次の出力が表示されます。

$python test_exc.py 
^Cinterrupted

例外が発生しなかったため、出力されio interruptedないことに注意してください。実際、コードを次のように変更します。

import signal,sys

def handleInt(sign,no):
    print "interrupted"

signal.signal(signal.SIGINT, handleInt)    # exception raised is IOError

try:
    sys.stdin.read(1)
except IOError:
    print "io interrupt"
else:
    # else is executed only if no exception was raised
    print "done"

あなたは得る:

$python test_exc.py 
^Cinterrupted

done

ヒットしても呼び出しがブロックされCtrl+Cないことに注意してください。したがって、プログラムを続行するには、何らかのキーを押す必要があります。シグナル ハンドラー内で例外を発生させると、 への呼び出しによって生成されたかのように例外が発生します。sys.stdin.read(1)sys.stdin.read(1)

import signal,sys

def handleInt(sign,no):
    print "interrupted"
    raise OSError

signal.signal(signal.SIGINT, handleInt)    # exception raised is IOError

try:
    sys.stdin.read(1)
except IOError:
    print "io interrupt"
else:
    # else is executed only if no exception was raised
    print "done"

サンプルラン:

$python test_exc.py 
^Cinterrupted
Traceback (most recent call last):
  File "test_exc.py", line 10, in <module>
    sys.stdin.read(1)
  File "test_exc.py", line 5, in handleInt
    raise OSError
OSError

注: 経由でデフォルトのシグナルハンドラにアクセスできますsignal.default_int_handler

于 2013-07-26T09:58:46.043 に答える
1

へのブロッキング呼び出しの後にシグナルを登録しようとすると、sys.stdin.read実際にはそこに到達しません。

そのため、Ctrl-C を押すと例外が発生KeyboardInterruptし、読み取りが中断され、try.

最初の例で実際にシグナル ハンドラーを登録すると、少し異なることが起こっています。割り込みはhandleIntコードによって処理されています。

于 2013-07-26T09:55:20.793 に答える