如何解决当作为子进程生成时,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 举报,一经查实,本站将立刻删除。