2017-10-13 4 views
1

を捕まえていない私は、高速キャプチャと処理のために例を取って、キーボード割り込みをキャッチするSIGINTイベントハンドラを追加しました:のpython picamera、キーボードのCtrl + C/SIGINTは<a href="http://picamera.readthedocs.io/en/release-1.12/recipes2.html" rel="nofollow noreferrer">pycamera docs</a>から

import io 
import time 
import threading 
import picamera 

# Create a pool of image processors 
done = False 
lock = threading.Lock() 
pool = [] 

def signal_handler(signal, frame): 
    global done 
    print 'You pressed Ctrl+C!' 
    done=True 
    sys.exit() 

signal.signal(signal.SIGINT, signal_handler) 
class ImageProcessor(threading.Thread): 
    def __init__(self): 
     super(ImageProcessor, self).__init__() 
     self.stream = io.BytesIO() 
     self.event = threading.Event() 
     self.terminated = False 
     self.daemon=True; 
     self.start() 

    def run(self): 
     # This method runs in a separate thread 
     global done 
     while not self.terminated: 
      # Wait for an image to be written to the stream 
      if self.event.wait(1): 
       try: 
        self.stream.seek(0) 
        # Read the image and do some processing on it 
        #Image.open(self.stream) 
        #... 
        #... 
        # Set done to True if you want the script to terminate 
        # at some point 
        #done=True 
       finally: 
        # Reset the stream and event 
        self.stream.seek(0) 
        self.stream.truncate() 
        self.event.clear() 
        # Return ourselves to the pool 
        with lock: 
         pool.append(self) 

def streams(): 
    while not done: 
     with lock: 
      if pool: 
       processor = pool.pop() 
      else: 
       processor = None 
     if processor: 
      yield processor.stream 
      processor.event.set() 
     else: 
      # When the pool is starved, wait a while for it to refill 
      time.sleep(0.1) 

with picamera.PiCamera() as camera: 
    pool = [ImageProcessor() for i in range(4)] 
    camera.resolution = (640, 480) 
    camera.framerate = 30 
    camera.start_preview() 
    time.sleep(2) 
    camera.capture_sequence(streams(), use_video_port=True) 

# Shut down the processors in an orderly fashion 
while pool: 
    with lock: 
     processor = pool.pop() 
    processor.terminated = True 
    processor.join() 

が、割り込み信号があります捕まえられない

camera.capture_sequence(streams(), use_video_port=True)が実行されるまでは、capture_sequenceが起動された後にシグナルハンドラが呼び出されないため、シグナルがキャッチされます。

私はPythonには新しいので、おそらく答えは簡単です。私はここで間違って何をしていますか?

EDIT:

私は信号が捕捉され、次のコードを削除する場合:あなたのコードで

yield processor.stream 

答えて

1

問題をあなたはthread.join()を使用していることがあり、それはあなたのプログラムが継続して使用すると、仕上げに入社し、そのスレッドまで待たなければならない意味し、メインスレッドをブロック。

シグナルはシグナルを受け取るシグナルなので、シグナルは常にスレッドによって捕捉されます。

はメインスレッドとCTRL + Cに対処する方法についての答えがたくさんありますが、私はコール)(参加するためにタイムアウトを追加し、あなたに3つのオプション、

ファーストを与える:

thread1.join(60)詳細here

2番目に、プログラムを強制終了するシグナルを処理する新しいプロセスを開始します。あなたが仕事のスレッドを開始する前

class Watcher(): 

    def __init__(self): 
     self.child = os.fork() 
     if self.child == 0: 
      return 
     else: 
      self.watch() 

    def watch(self): 
     try: 
      os.wait() 
     except KeyboardInterrupt: 
      self.kill() 
     sys.exit() 

    def kill(self): 
     try: 
      os.kill(self.child, signal.SIGKILL) 
     except OSError: 
      pass 

def main(): 
    init() 
    Watcher() 
    start_your_thread1() 
    start_your_thread2() 
    start_your_thread3() 

のように、最終的に、あなたのオリジナルの方法、複雑な生産と消費者の道をウォッチャーを開始

最終的なjoin()を削除し、メインスレッド用のタスクを追加するだけです。

私はPythonでマルチスレッドプログラムの2つの問題を解決しています。(1)シグナルは任意のスレッド(不正機能です)に配信される可能性があります。信号が待たされると、シグナルは無視されます(バグです)。ウォッチャーについて より詳しくは、本The Little Book of Semaphores

0

を、done変数はグローバル変数です。 したがって、関数内で変更する場合は、キーワードglobalを使用する必要があります。そうでない場合は、ローカル変数になります。

あなたは、このようにコードを修正する必要があります。

import signal 
import sys 

done = False 


def signal_handler(signal, frame): 
    global done 
    print('You pressed Ctrl+C!') 
    done = True 
    sys.exit() 


signal.signal(signal.SIGINT, signal_handler) 
+0

の付録Aであるあなたは、コードの修正について正しいですが、問題はsignal_handler機能が –

+0

ご使用のプラットフォームのWindowsは何と呼ばれることはありませんので、SIGのint型の信号が捕捉されることはありませんでしょうか? Posix? –

関連する問題