![](/img/trans.png)
[英]python multiprocessing - sending child process logging to GUI running in parent
[英]Multiprocessing: Parent/Child w/ GUI (tkinter)
我正在創建一個帶有 UI 的父程序,它產生多個子程序,也帶有 GUI。 所有子進程都需要與父進程對話(嘗試 PIPE atm)。 Parent 使用 QUEUE 終止所有進程。
編輯:程序在 Raspberry Pi 4 w/Raspbian OS 和 python 3.7.3 上運行。
主程序:bridge.py
import tkinter as tk
from time import sleep
import multiprocessing as mp
import os
import sys
import simple
class Main_Comm():
def __init__(self):
self.kill_queue = mp.Queue()
self.p_conn, self.ch_conn = mp.Pipe()
print("MAIN: PIPE: child: {}".format(self.ch_conn))
self.proc = mp.Process(target=simple.my_dev, \
args=(self.kill_queue, self.ch_conn, ))
self.proc.start()
def Stop_Devices(self):
#self.kill_queue.put(True)
self.proc.join()
print("Wait for processes to finish ...")
sleep(2)
print("Device OFF!")
def Info(self):
print("Info: QUEUE {}, PIPE {}".format(self.kill_queue, self.ch_conn))
class MainApp_bridge(tk.Tk):
def __init__(self, master=None, title="Default"):
#super().__init__()
tk.Tk.__init__(self)
self.title(title)
self.btn = tk.Button(self, text="QUIT", command=self.on_quit)
self.btn.pack(padx=20, pady=20)
self.communicator = Main_Comm()
self.communicator.Info()
self.mainloop()
def on_quit(self):
print("Sending termination message via QUEUE ...")
self.communicator.Stop_Devices()
sleep(1)
print("Shutting down main tread, HAL ...")
sleep(1)
self.destroy()
def main():
root_bridge = MainApp_bridge(title="BRIDGE")
if __name__ == "__main__":
main()
# EOF
和一個孩子(simple.py)
import tkinter as tk
import os
import random
from time import sleep
import sys
class MainApp_simple(tk.Tk):
def __init__(self, parent=None, title="Device",
FLAG=False, kq=None, chc=None):
#super().__init__()
tk.Tk.__init__(self)
self.title(title)
self.b_QUIT = tk.Button(self, text="QUIT", command=self.on_quit)
self.b_QUIT.pack(side="top", padx=30, pady=30)
self.window=self
self.kq = kq
self.chc = chc
self.comm_agent = communicator( self.window, self.kq, self.chc )
self.mainloop()
def on_quit(self):
print("CHILD: Quitting ...")
self.destroy()
class Dev_comm():
def __init__(self, win, kq, chc):
self.kq = kq
self.chc = chc
self.win = win
self.mypid = os.getpid()
print("CHILD: PID is {} and PIPE is {}".format(self.mypid, chc))
def my_dev( kill_queue, child_comm ):
root_simple = MainApp_simple(
parent=None,
title="CHILD",
FLAG=False,
kq=kill_queue,
chc=child_comm
)
# EOF sim.py
每個程序都可以自己正常工作。 如果我從橋上取出 GUI,它就可以工作。 然而,總的來說,我得到了這個:
CHILD: MainApp - pre __init__ .... flushing
MAIN: PIPE: child: <multiprocessing.connection.Connection object at 0xb5989750>
Info: QUEUE <multiprocessing.queues.Queue object at 0xb5dc39d0>, PIPE <multiprocessing.connection.Connection object at 0xb5989750>
CHILD: Entered my_dev function ... flushing ...
XIO: fatal IO error 25 (Inappropriate ioctl for device) on X server ":0.0"
after 47 requests (47 known processed) with 2 events remaining.
X Error of failed request: BadIDChoice (invalid resource ID chosen for this connection)
Major opcode of failed request: 45 (X_OpenFont)
Resource id in failed request: 0x2c00004
Serial number of failed request: 114
Current serial number in output stream: 120
我就是想不通,順便說一句; flushing 沒有提供任何新信息。 錯誤信息以 XIO 開頭...
首先,我認為它與輪詢管道和隊列有關,這些管道和隊列干擾了 mainloop()……但顯然不是。
非常感謝您的幫助。
干杯,拉德克
編輯:我認為兩個 tk.Tk 調用之間可能存在一些干擾,但是只要父進程在終端中運行,我就可以使用 GUI 運行多個子進程。 甚至管道和隊列也能工作......它是父 GUI......
Jason Harper 實際上提供了一個解決方案:SPAWN 而不是 FORK。
啟動似乎有點慢,但一切都按預期運行。 即使在進程之間輪詢隊列和管道也能很好地工作。
謝謝你。 拉德克
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.