蟒蛇picamera,键盘上的Ctrl + C/SIGINT没有抓到

问题描述:

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 

的问题还有就是你正在使用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

在你的代码中,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的? –