6

multithreading読む前に重複しているとは思わないでください。とについて多くの質問がありますが、keyboard interruptos.systemを検討しているものは見つかりませんでした。重要なようです。

ワーカースレッドでいくつかの外部呼び出しを行うPythonスクリプトがあります。を押すと終了したいのですctrl+cが、メインスレッドが無視しているようです。

このようなもの:

from threading import Thread
import sys
import os

def run(i):
    while True:
        os.system("sleep 10")
        print i

def main():
    threads=[]
    try:
        for i in range(0, 3):
            threads.append(Thread(target=run, args=(i,)))
            threads[i].daemon=True
            threads[i].start()
        for i in range(0, 3):
            while True:
                threads[i].join(10)
                if not threads[i].isAlive():
                    break

    except(KeyboardInterrupt, SystemExit):
        sys.exit("Interrupted by ctrl+c\n")


if __name__ == '__main__': 
    main() 

驚いたことに、に変更os.system("sleep 10")すると正常に動作しtime.sleep(10)ます。

4

2 に答える 2

6

使用しているオペレーティング システムとシェルがわかりません。Mac OS X と Linux を zsh で説明します (bash/sh も同様に動作するはずです)。

Ctrl+C を押すと、現在の端末のフォアグラウンドで実行されているすべてのプログラムがシグナル SIGINT を受け取ります。あなたの場合、それはあなたのメインのpythonプロセスであり、os.systemによって生成されたすべてのプロセスです。

os.system によって生成されたプロセスは、実行を終了します。通常、Python スクリプトが SIGINT を受け取ると、KeyboardInterrupt 例外が発生しますが、メイン プロセスは SIGINT を無視しますos.system()。Pythonos.system() は標準 C 関数 system()を呼び出します。これにより、呼び出しプロセスは SIGINT を無視します ( man Linux / man Mac OS X )。

したがって、どちらの Python スレッドも SIGINT を受信しません。それを取得するのは子プロセスだけです。

os.system() 呼び出しを削除すると、Python プロセスは SIGINT の無視を停止し、KeyboardInterrupt.

os.system("sleep 10")と交換できますsubprocess.call(["sleep", "10"])subprocess.call()プロセスに SIGINT を無視させません。

于 2013-01-10T09:09:22.337 に答える
1

私が最初にPythonマルチスレッディングを学んだとき、私が数えることができたよりも何度もこの同じ問題を抱えていました。

ループ内にスリープ呼び出しを追加すると、メインスレッドがブロックされます。これにより、例外を引き続き聞いて受け入れることができます。あなたがしたいのは、Eventクラスを利用して、実行を中断するための終了フラグとして機能するイベントを子スレッドに設定することです。このフラグはKeyboardInterrupt例外に設定できます。そのためのexcept句をメインスレッドに配置するだけです。

Python固有のスリープとOSと呼ばれるスリープの間のさまざまな動作で何が起こっているのか完全にはわかりませんが、私が提供している救済策は、希望する最終結果がどうなるかについてはうまくいくはずです。推測を提供するだけで、1つと呼ばれるOSは、おそらく別の方法でインタプリタ自体をブロックしますか?

一般に、スレッドが必要なほとんどの状況では、メインスレッドが何かを実行し続けることに注意してください。この場合、単純な例の「スリープ」が暗示されます。

http://docs.python.org/2/library/threading.html#event-objects

于 2013-01-09T18:50:19.673 に答える