gpt4 book ai didi

Python 3 - 在用户将鼠标悬停在 GUI 窗口上之前,主线程未检测到后台线程中的键盘中断

转载 作者:太空宇宙 更新时间:2023-11-04 04:26:40 25 4
gpt4 key购买 nike

我编写了一个基于 Python 3 TkInter 的 GUI 应用程序,它在后台启动一个工作线程。工作线程完成后,它等待两秒钟(这是为了避免可能的竞争条件),然后发送一个 KeyboardInterrupt 告诉主线程它可以关闭。

预期行为:运行该程序会启动一个 GUI 窗口,向控制台打印一些文本,之后该程序会自动关闭。

实际行为:它不会自动关闭,只有在用户将鼠标悬停在 GUI 窗口区域上或按下键盘上的某个键后才会自动关闭!除此之外,程序运行时没有报告任何错误。

任何人都知道为什么会发生这种情况,以及如何解决这个问题?我已经尝试将 KeyboardInterrupt 包装到一个单独的函数中,然后通过 timer object 调用它,但这会导致相同的行为。

我已经能够在两台运行 Python 3.5.2 的不同 Linux 机器上重现这个问题。和3.6.6分别。

#! /usr/bin/env python3

import os
import threading
import _thread as thread
import time
import tkinter as tk
import tkinter.scrolledtext as ScrolledText

class myGUI(tk.Frame):

# This class defines the graphical user interface

def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.root = parent
self.build_gui()

def build_gui(self):
# Build GUI
self.root.title('TEST')
self.root.option_add('*tearOff', 'FALSE')
self.grid(column=0, row=0, sticky='ew')
self.grid_columnconfigure(0, weight=1, uniform='a')

# Add text widget to display logging info
st = ScrolledText.ScrolledText(self, state='disabled')
st.configure(font='TkFixedFont')
st.grid(column=0, row=1, sticky='w', columnspan=4)

def worker():
"""Skeleton worker function, runs in separate thread (see below)"""

# Print some text to console
print("Working!")
# Wait 2 seconds to avoid race condition
time.sleep(2)
# This triggers a KeyboardInterrupt in the main thread
thread.interrupt_main()

def main():
try:
root = tk.Tk()
myGUI(root)
t1 = threading.Thread(target=worker, args=[])
t1.start()
root.mainloop()
t1.join()
except KeyboardInterrupt:
# Close program if subthread issues KeyboardInterrupt
os._exit(0)

main()

(Github Gist 链接到上述脚本 here )

最佳答案

root.mainloop() mainloop 是阻塞的,Python 中的挂起(可拦截)信号仅在字节码指令执行之间进行检查。 t1.join() 在你的代码中实际上永远不会被执行。

因为 mainloop block 等待转发的硬件中断,为了解锁你必须通过例如提供它们像你看到的那样悬停在 window 上。只有然后解释器检测到未决的KeyboardInterrupt。这就是 Python 中信号处理的工作原理。

解决一般问题可能意味着找到方法来解除阻塞 I/O 调用的阻塞,方法是通过外部注入(inject)解除阻塞所需的内容,或者一开始就不使用阻塞调用。

对于您的具体设置,您可以使用未处理的 SIGTERM 终止整个进程,但是当然,这样做会非常非常难看,而且在这里也没有必要。如果您只是寻找一种使窗口超时的方法,您可以使用 tkinter.Tk.after 方法超时(显示 herehere ),或者摆脱 mainloop 并自己运行循环 ( here )。

后者可能看起来像:

def main():
root = tk.Tk()
myGUI(root)

t1 = threading.Thread(target=worker, args=[])
t1.start()

while True:
try:
root.update_idletasks()
root.update()
time.sleep(0.1)
except KeyboardInterrupt:
print('got interrupt')
break

t1.join()

关于Python 3 - 在用户将鼠标悬停在 GUI 窗口上之前,主线程未检测到后台线程中的键盘中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53375415/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com