使用 Python 和 tkinter 进行多处理

Posted

技术标签:

【中文标题】使用 Python 和 tkinter 进行多处理【英文标题】:Multiprocessing with Python and tkinter 【发布时间】:2020-09-28 00:51:20 【问题描述】:

这似乎微不足道,但我无法解释......

我有以下工作的 tkinter 代码 sim.py:

import tkinter as tk
import os
import random
import time

class MainApp(tk.Tk):
    def __init__(self, parent=None, title="Device", *args, **kwargs):
        super().__init__()
        print("CHILD.GUI: Entered __init__")
        self.title(title)
        tk.Button(self, text="QUIT", command=self.on_quit).pack(side="top", padx=30, pady=30)
        """ <RUN> """
        self.mainloop()

    def on_quit(self):
        print("Quitting ...")
        self.destroy()

def main():
    root = MainApp()

def my_dev( kill_queue, child_conn):
    print ("CHILD: Entered device function ...")
    root = MainApp()


if __name__ == "__main__":
    main()

# EOF sim.py

但是当我尝试从主程序 main.py 将其作为子程序执行时:

import multiprocessing as mp
import os
import sys
import time
import signal
import tkinter as tk
import sim

nproc = 1
result = 0
def signal_handler(signal, frame):
    print ('\nCaught interrupt, cleaning up...')
    print (process.terminate())
    sys.exit(0)

signal.signal(signal.SIGINT, signal_handler)

if __name__ == '__main__':
    kill_queue = mp.Queue()
    parent_connection, child_connection = mp.Pipe()
    process = mp.Process(target=sim.my_dev, args=(kill_queue,child_connection,))
    process.start()
    print("Spawning process with PID:".format(process.pid) )
    # finite number of runs ...
    for dummy in range(100):
        while parent_connection.poll():
            result = parent_connection.recv()
        print("Data: :8.2f".format(result), end="")
        print("\r", end="")
        time.sleep(.1)
    # Finishing up ... sending a kill signal
    print("\n\n")
    kill_queue.put(True)
    process.join()

    print ('Main thread done.')

我什么也得不到。它打印“儿童:输入设备功能”,就是这样。 “儿童:GUI”不打印。没有错误。我可以看到 CHILD 进程与

ps ax

并在主程序完成时终止。

请注意,我已经删除了孩子中的 PIPE 部分……实际上,如果我去掉 GUI,那部分就可以工作了。

有什么想法吗?

谢谢你, 拉德克

编辑:修复(希望)父评论。还修复了窗口标题。它仍然没有运行。尝试冲洗...

编辑:在 my_dev 中打印后刷新,并且在 root = MainApp() 之后没有给出任何结果...

编辑:flush 做了一些事情(方便的小事)。我将 tkinter 添加到 main.py 中(只需 tk.Tk() 进行初始化)。突然,代码进入MainApp(显示:CHILD.GUI: Entered init)报错:

2020-06-09 01:15:45.982 python[50273:22418845] 无法从服务器检索字体!在本地注册系统字体...

顺便说一句,50273 是生成进程的正确 PID。

我还直接将我的 GUI 函数添加到 main.py ...同样的错误。该错误似乎与产生新进程有关......我没有找到任何解决方案......建议?回复>

【问题讨论】:

我再次检查:由于某种原因,CHILD 进程是僵尸(ps ax 中的 Z+)。我还是不明白。 R> 子进程中的控制台输出可能会被缓存,请尝试在每个打印语句后添加sys.stdout.flush()。顺便说一句,tk.Tk() 没有父级,因此应删除 MainApp.__init__() 中的 parent 参数。 【参考方案1】:

所以有一个答案......有点。

该代码在 Debian Linux(准确地说是 Raspbian)上完美运行。

我的 Mac 上仍然收到有关缺少字体的错误消息: 2020-06-09 01:15:45.982 python[50273:22418845] Could not retrieve fonts from the server! Registering system fonts locally... 正如我上面提到的,它只在主程序中包含tk.Tk() 后出现在系统刷新中。

为了完整起见:我使用自制软件在我的 Mac 上安装了 pyenv。所有 python3 包都是通过 pip 安装的。其他一切似乎都按预期工作。上面的 tkinter 代码在作为主程序执行时运行良好。任何时候通过多处理调用它都不起作用。

最终,我需要程序在 Linux 上运行;我使用我的 Mac 对非硬件部分(如 GUI)进行编码。如果它在 Mac 上也能正常工作,那就太好了。

建议?

和平! 拉德克

【讨论】:

以上是关于使用 Python 和 tkinter 进行多处理的主要内容,如果未能解决你的问题,请参考以下文章

Python多处理-TypeError:无法腌制'_tkinter.tkapp'对象

使用 tkinter 进行多处理不会产生多个 GUI

在 Windows,Python3.8 上使用多处理时如何更新 tkinter 应用程序中的状态

Python:在使用多处理时更新 Tkinter

使用 Tkinter 和 Selenium 进行多处理

在多处理之前调用 Tkinter 会导致多个窗口?