Restructured multiprocessing infrastructure

This commit is contained in:
Balthasar Reuter
2018-05-11 20:17:22 +02:00
parent ee1518086a
commit 4d34d49e51
3 changed files with 79 additions and 43 deletions

View File

@@ -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()

View File

@@ -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()
@@ -58,7 +60,7 @@ class PyQt5Gui(Gui):
def restart(self): def restart(self):
self._app.exit(-2) self._app.exit(123)
def sendAck(self): def sendAck(self):
@@ -210,9 +212,10 @@ class PyQt5Receiver(QThread):
def run(self): def run(self):
while True: while self._conn:
for c in mp.connection.wait(self._conn):
try: try:
state = self._conn.recv() state = c.recv()
except EOFError: except EOFError:
break break
else: else:

View File

@@ -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()
while status_code == 123:
event = self.conn.recv()
if str(event) != 'start': if str(event) != 'start':
continue continue
status_code = start_worker(config, conn) status_code = self.run_camera()
print('Camera exit') print('Camera exit')
if status_code != -1: sys.exit(status_code)
return 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])