蟒蛇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)
你说得对有关代码更正的附录A,但问题是SIG INT信号没有抓住这样的signal_handler功能是从来没有所谓的 –
你是什么平台的Windows? Posix的? –