2016-11-02 20 views
3

run_forever()という関数をスレッド内で実行したいとしますが、Cntrl + Cを押しても '停止可能'にします。私はthreading.ThreadStoppableThreadサブクラスを使ってこれを行う方法を見てきましたが、これらはターゲット関数をそのサブクラスに 'コピー'する必要があります。代わりに機能を「どこに」置いておきたいのですか?無限ループであるターゲット関数で停止可能なスレッドを作成する方法

は、次の例を考えてみましょう:

import time 
import threading 

def run_forever():    # An externally defined function which runs indefinitely 
    while True: 
     print("Hello, world!") 
     time.sleep(1) 

class StoppableThread(threading.Thread): 
    """Thread class with a stop() method. The thread itself has to check 
    regularly for the stopped() condition.""" 

    def __init__(self, *args, **kwargs): 
     super(StoppableThread, self).__init__(*args, **kwargs) 
     self._stop = threading.Event() 

    def stop(self): 
     self._stop.set() 

    def stopped(self): 
     return self._stop.isSet() 

    def run(self): 
     while not self.stopped(): 
      run_forever()    # This doesn't work 
      # print("Hello, world!")  # This does 
      self._stop.wait(1) 

thread = StoppableThread() 
thread.start() 
time.sleep(5) 
thread.stop() 

ターゲット機能run_foreverが終了したことがないwhileループそのものです。しかし、望ましい動作を得るためには、私が理解しているように、wait()コマンドはそのwhileループの中になければなりません。

run_forever()機能を変更せずに目的の動作を達成する方法はありますか?

+2

あなたは、単にあなたのプログラムが「CNTRL + Cを押して、 『停止可能』」になりたい場合は - ときに私私が意味するように解釈した「ハングしません'' Thread = StoppableThread(daemon = True) 'のように、Threadオブジェクトのデーモン属性をTrueに設定することができます。 – Billy

+0

[Billy](http://stackoverflow.com/users/7007605/billy)、私はすでにデーモン化されたスレッドでこのような実装をしていますが、これらは突然停止します。私は優雅に停止するものが欲しいです。 –

+1

'run_forever'関数を絶対に変更できない場合は、ここの答えの2番目の例と同様に、プラットフォームAPIに直接アクセスすることをお勧めします:http://stackoverflow.com/a/325528/7007605 – Billy

答えて

1

私はそれが可能であるとは思わない。
ところで、あなたは ThreadWithExcから2番目の解決策を試しましたか?the post以前にリンクしましたか?
ループが純粋なPython(例えば、no sleep)でビジー状態になっている場合は動作します。そうでなければ、multiprocessingに切り替えてサブプロセスを終了します。ここでうまくいけば、正常に終了コードがある(* NIXのみ):

from multiprocessing import Process 
from signal import signal, SIGTERM 
import time 

def on_sigterm(*va): 
    raise SystemExit 

def fun(): 
    signal(SIGTERM, on_sigterm) 
    try: 
     for i in xrange(5): 
      print 'tick', i 
      time.sleep(1) 
    finally: 
     print 'graceful cleanup' 

if __name__=='__main__': 
    proc = Process(target=fun) 
    proc.start() 
    time.sleep(2.5) 
    proc.terminate() 
    proc.join() 
関連する問題