当作为子进程生成时,tkinter中断

问题描述

我正尝试在python中创建一个“提醒” GUI应用。

当我实现Tkinter在主模块中打开弹出窗口时,一切正常。但是,当我尝试在从主流程派生的子流程中创建窗口时,我收到MacOS错误消息和显示“ python意外退出”的窗口,看起来该流程正在尝试访问内核空间?

我该如何解决

这是代码-

import tkinter as tk 
from tkmacosx import Button
from multiprocessing import Process,Queue
from json import load as loadjson
import time
import atexit
import logging
import logging.handlers
import os
import signal

def kill_children(da_q: Queue) -> None:
    while da_q.empty() == False:
        proc_id_to_kill = da_q.get()
        os.kill(proc_id_to_kill,signal.SIGTERM)


def init_logging(requested_log_level: str = logging.DEBUG) -> logging.getLogger:
    logger = logging.getLogger(__name__)
    logger.setLevel(requested_log_level)
    ch = logging.StreamHandler()
    ch.setLevel(requested_log_level)
    formatter = logging.Formatter("%(asctime)s - [%(name)s/function_name=%(funcName)s/pid=%(process)d/pname=%(processName)s] - %(levelname)s - %(message)s ")
    ch.setFormatter(formatter)
    logger.addHandler(ch)
    ch2 = logging.handlers.RotatingFileHandler('reminders.log')
    ch2.setLevel(requested_log_level)
    ch2.setFormatter(formatter)
    logger.addHandler(ch2)
    return logger


def pop_up_window(reminder_obj: dict) -> None:
    logger.info("started pop_up_window process")
    logger.debug("threshold="+str(int(reminder_obj["reminder_frequency_in_minutes"])*60))
    start_time = time.time()
    logger.debug(f"start time={start_time}")
    time.sleep(10)
    cur_time = time.time()
    logger.debug(f"cur_time={cur_time}")
    diff = cur_time - start_time
    logger.debug(f"diff={diff}")
    while diff < (int(reminder_obj["reminder_frequency_in_minutes"])*60):
        time.sleep(10)
        cur_time = time.time()
        logger.debug(f"cur_time={cur_time}")
        diff = cur_time - start_time
        logger.debug(f"diff={diff}")
    if diff >= (int(reminder_obj["reminder_frequency_in_minutes"])*60):
        logger.info("reminder time reached. generate window.")
        window = tk.Tk()
        window.eval('tk::PlaceWindow . Center')
        window.rowconfigure(0,minsize=50,weight=1)
        window.columnconfigure([0,1,2],weight=1)
        window.title("Reminder: ")
        hide_btn = Button(master=window,text="hide",command=hide_window,fg="Black")
        label = tk.Label(text="drink water")
        label.grid(row=0,column=1)
        hide_btn.grid(row=1,column=1)
        window.mainloop()
    
    
    def hide_window() -> None:
        logger.debug(f"destroy window {__name__}")
        exit(0)


def proc_handler(reminder_obj: list,da_q: Queue) -> None:
    logger.debug("started handler for reminder=")
    logger.debug(reminder_obj)
    logger.debug("starting popup window subprocess forever,till parent kills it...")
    while True:
        p = Process(target=pop_up_window,args=(reminder_obj,))
        p.start()
        logger.debug("started. pid="+str(p.pid))
        q.put(p.pid)
        p.join()

if __name__ == "__main__":
    logger = init_logging()
    logger.debug("started.")
    atexit.register(kill_children)
    logger.debug("registered kill-children on exit")
    q = Queue()
    logger.debug("created process-safe queue")
    with open("reminders.json") as rmf:
        reminders = loadjson(rmf)
    logger.info("loaded reminders config file successfully.")
    reminder_handler_processes = []
    for reminder in reminders:
        logger.info("initing processes..")
        reminder_handler = Process(target=proc_handler,args=(reminder,q,))
        reminder_handler_processes.append(reminder_handler)
    logger.debug("processes=")
    logger.debug(repr(reminder_handler_processes))
    logger.info("starting handlers...")
    for handler_proc in reminder_handler_processes:
        handler_proc.start()
        logger.debug("started ... pid="+str(handler_proc.pid))
        q.put(handler_proc.pid)
    

补充文件

reminders.json

[
    {
        "reminder_name":"get_up_and_walk","reminder_message":"Get up and walk","reminder_frequency_in_minutes":1
    },{
        "reminder_name":"drink_water","reminder_message":"Drink Some Water","reminder_frequency_in_minutes":2
    }
]

requirements.txt ,以防您想要创建虚拟视频并自己进行测试。

astroid==2.4.2
colour==0.1.5
isort==4.3.21
lazy-object-proxy==1.4.3
mccabe==0.6.1
pylint==2.5.3
six==1.15.0
tk==0.1.0
tkmacosx==0.1.4
toml==0.10.1
typed-ast==1.4.1
wrapt==1.12.1

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)