2017-10-13 39 views
1

pycamera docs我把快速採集和處理的例子,並增加了SIGINT事件處理程序來捕獲鍵盤中斷:蟒蛇picamera,鍵盤上的Ctrl + C/SIGINT沒有抓到

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的新手,所以答案很簡單。我在這裏做錯了什麼?

編輯:

如果我刪除下面的代碼信號被捕獲:

yield processor.stream 

回答

1

的問題還有就是你正在使用thread.join(),它阻塞主線程,這意味着你的程序要等到你加入面漆線程繼續。

信號總是被主進程捕獲,因爲它是接收信號的那個,它是有線程的進程。

有很多有關如何處理主線程和CTRL + C的答案,我給你三個選擇,

首先,添加超時加入()調用:

thread1.join(60)詳細here

二,啓動一個新的進程來處理信號殺死程序。你開始工作線程之前

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(),併爲主線程添加一些任務。 (1)信號可能被傳遞到任何線程(這只是一個錯誤),(2)如果線程是這樣的得到的信號正在等待,信號被忽略(這是一個錯誤)。 有關看守的更多細節在書中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,但問題是SIG INT信號沒有抓住這樣的signal_handler功能是從來沒有所謂的 –

+0

你是什麼平臺的Windows? Posix的? –