Restructured multiprocessing infrastructure
This commit is contained in:
@@ -24,7 +24,7 @@ class Photobooth:
|
|||||||
|
|
||||||
self._conn = conn
|
self._conn = conn
|
||||||
|
|
||||||
self.initCamera(config, camera)
|
self.initCamera(config, camera())
|
||||||
self.initGpio(config)
|
self.initGpio(config)
|
||||||
|
|
||||||
self.triggerOff()
|
self.triggerOff()
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import multiprocessing as mp
|
||||||
|
|
||||||
from PIL import ImageQt
|
from PIL import ImageQt
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QObject, QPoint, QThread, QTimer, pyqtSignal
|
from PyQt5.QtCore import Qt, QObject, QPoint, QThread, QTimer, pyqtSignal
|
||||||
@@ -35,13 +37,13 @@ class PyQt5Gui(Gui):
|
|||||||
cfg.getInt('Printer', 'height')), True)
|
cfg.getInt('Printer', 'height')), True)
|
||||||
|
|
||||||
|
|
||||||
def run(self, conn):
|
def run(self, camera_conn):
|
||||||
|
|
||||||
receiver = PyQt5Receiver(conn)
|
receiver = PyQt5Receiver([camera_conn])
|
||||||
receiver.notify.connect(self.handleState)
|
receiver.notify.connect(self.handleState)
|
||||||
receiver.start()
|
receiver.start()
|
||||||
|
|
||||||
self._conn = conn
|
self._conn = camera_conn
|
||||||
|
|
||||||
self.showStart()
|
self.showStart()
|
||||||
|
|
||||||
@@ -57,8 +59,8 @@ class PyQt5Gui(Gui):
|
|||||||
|
|
||||||
|
|
||||||
def restart(self):
|
def restart(self):
|
||||||
|
|
||||||
self._app.exit(-2)
|
self._app.exit(123)
|
||||||
|
|
||||||
|
|
||||||
def sendAck(self):
|
def sendAck(self):
|
||||||
@@ -210,13 +212,14 @@ class PyQt5Receiver(QThread):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
while True:
|
while self._conn:
|
||||||
try:
|
for c in mp.connection.wait(self._conn):
|
||||||
state = self._conn.recv()
|
try:
|
||||||
except EOFError:
|
state = c.recv()
|
||||||
break
|
except EOFError:
|
||||||
else:
|
break
|
||||||
self.handle(state)
|
else:
|
||||||
|
self.handle(state)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ try:
|
|||||||
except DistributionNotFound:
|
except DistributionNotFound:
|
||||||
__version__ = 'unknown'
|
__version__ = 'unknown'
|
||||||
|
|
||||||
from multiprocessing import Pipe, Process
|
import multiprocessing as mp
|
||||||
import importlib
|
import importlib
|
||||||
|
import sys
|
||||||
|
|
||||||
from . import camera, gui
|
from . import camera, gui
|
||||||
from .Config import Config
|
from .Config import Config
|
||||||
@@ -33,40 +34,68 @@ def lookup_and_import(module_list, name, package=None):
|
|||||||
return getattr(import_module, result[1])
|
return getattr(import_module, result[1])
|
||||||
|
|
||||||
|
|
||||||
def start_worker(config, conn):
|
class CameraProcess(mp.Process):
|
||||||
|
|
||||||
while True:
|
def __init__(self, config, conn):
|
||||||
|
|
||||||
|
super().__init__()
|
||||||
|
self.daemon = True
|
||||||
|
|
||||||
|
self.cfg = config
|
||||||
|
self.conn = conn
|
||||||
|
|
||||||
|
|
||||||
|
def run_camera(self):
|
||||||
|
|
||||||
|
# while True:
|
||||||
try:
|
try:
|
||||||
Camera = lookup_and_import(
|
cap = lookup_and_import(
|
||||||
camera.modules, config.get('Camera', 'module'), 'camera')
|
camera.modules, self.cfg.get('Camera', 'module'), 'camera')
|
||||||
|
|
||||||
with Camera() as cap:
|
photobooth = Photobooth(self.cfg, cap, self.conn)
|
||||||
photobooth = Photobooth(config, cap, conn)
|
return photobooth.run()
|
||||||
return photobooth.run()
|
|
||||||
|
|
||||||
except BaseException as e:
|
except BaseException as e:
|
||||||
conn.send( gui.ErrorState('Camera error', str(e)) )
|
self.conn.send( gui.ErrorState('Camera error', str(e)) )
|
||||||
event = conn.recv()
|
event = self.conn.recv()
|
||||||
if str(event) in ('cancel', 'ack'):
|
if str(event) in ('cancel', 'ack'):
|
||||||
return -1
|
return 123
|
||||||
else:
|
else:
|
||||||
print('Unknown event received: ' + str(event))
|
print('Unknown event received: ' + str(event))
|
||||||
raise RuntimeError('Unknown event received', str(event))
|
raise RuntimeError('Unknown event received', str(event))
|
||||||
|
|
||||||
|
|
||||||
def main_worker(config, conn):
|
def run(self):
|
||||||
|
|
||||||
while True:
|
status_code = 123
|
||||||
event = conn.recv()
|
|
||||||
|
|
||||||
if str(event) != 'start':
|
while status_code == 123:
|
||||||
continue
|
event = self.conn.recv()
|
||||||
|
|
||||||
status_code = start_worker(config, conn)
|
if str(event) != 'start':
|
||||||
print('Camera exit')
|
continue
|
||||||
|
|
||||||
if status_code != -1:
|
status_code = self.run_camera()
|
||||||
return status_code
|
print('Camera exit')
|
||||||
|
|
||||||
|
sys.exit(status_code)
|
||||||
|
|
||||||
|
|
||||||
|
class GuiProcess(mp.Process):
|
||||||
|
|
||||||
|
def __init__(self, argv, config, conn):
|
||||||
|
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.argv = argv
|
||||||
|
self.cfg = config
|
||||||
|
self.conn = conn
|
||||||
|
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
|
||||||
|
Gui = lookup_and_import(gui.modules, self.cfg.get('Gui', 'module'), 'gui')
|
||||||
|
sys.exit(Gui(self.argv, self.cfg).run(self.conn))
|
||||||
|
|
||||||
|
|
||||||
def run(argv):
|
def run(argv):
|
||||||
@@ -75,26 +104,30 @@ def run(argv):
|
|||||||
|
|
||||||
config = Config('photobooth.cfg')
|
config = Config('photobooth.cfg')
|
||||||
|
|
||||||
gui_conn, worker_conn = Pipe()
|
gui_conn, camera_conn = mp.Pipe()
|
||||||
|
|
||||||
worker = Process(target=main_worker, args=(config, worker_conn), daemon=True)
|
camera_worker = CameraProcess(config, camera_conn)
|
||||||
worker.start()
|
camera_worker.start()
|
||||||
|
|
||||||
Gui = lookup_and_import(gui.modules, config.get('Gui', 'module'), 'gui')
|
gui_worker = GuiProcess(argv, config, gui_conn)
|
||||||
status_code = Gui(argv, config).run(gui_conn)
|
gui_worker.start()
|
||||||
|
|
||||||
worker.join(1)
|
gui_conn.close()
|
||||||
return status_code
|
camera_conn.close()
|
||||||
|
|
||||||
|
gui_worker.join()
|
||||||
|
camera_worker.join(5)
|
||||||
|
return gui_worker.exitcode
|
||||||
|
|
||||||
|
|
||||||
def main(argv):
|
def main(argv):
|
||||||
|
|
||||||
known_status_codes = {
|
known_status_codes = {
|
||||||
-1: 'Initializing photobooth',
|
999: 'Initializing photobooth',
|
||||||
-2: 'Restarting photobooth and reloading config'
|
123: 'Restarting photobooth and reloading config'
|
||||||
}
|
}
|
||||||
|
|
||||||
status_code = -1
|
status_code = 999
|
||||||
|
|
||||||
while status_code in known_status_codes:
|
while status_code in known_status_codes:
|
||||||
print(known_status_codes[status_code])
|
print(known_status_codes[status_code])
|
||||||
|
|||||||
Reference in New Issue
Block a user