为什么 Tkinter 窗口在 macOS 中的交互式会话(空闲/REPL)中没有在"销毁"时关闭?



我有一个函数显示一个GUI窗口,用户可以在其中输入密码。我在开发过程中经常使用IDLE shell,所以使用getpass不是一个选择。

此函数是实用程序脚本的一部分,该脚本具有我希望能够使用的其他函数(在使用此函数提交密码后)。

import tkinter

def password_from_user():
password = None

def get_password(*__):
nonlocal password
password = entry.get()
window.destroy()

window = tkinter.Tk()
entry = tkinter.Entry(window, width=40, show='*')
entry.bind('<Return>', get_password)
entry.pack()
entry.focus_set()

window.mainloop()

return password

密码被存储并从函数返回。然而,Tkinter窗口保持打开状态。我可以按+Tab切换回IDLE shell,但这有点不方便。我希望这个窗口完全关闭。

如果我将其作为脚本运行,当然,所有内容都将在末尾关闭:

if __name__ == '__main__':
print(password_from_user())

但是,我只需要这个函数用于IDLE会话。如果我只使用命令行,我将使用getpass,这将绰绰有余。

编辑1:我试过使用destroyquit。他们两个都不适合我。 编辑2:刚刚在Windows机器上测试了Python 3.8.5。它的工作原理。所以,我很确定这和macOS有关。

找到了一个令我满意的解决方案。

将Tkinter代码保存在单独的模块中(例如,_password_box_ui.py):

import tkinter
password = None
def get_password(*__):
global password
password = entry.get()
window.quit()
window = tkinter.Tk()
window.title('Password')
entry = tkinter.Entry(window, width=40, show='*')
entry.bind('<Return>', get_password)
entry.pack()
entry.focus_set()
window.mainloop()
print(password)

然后,在另一个模块(我将在IDLE shell中导入)中,使用如下函数:

import pathlib
import subprocess
import sys

def password_from_user():
process = subprocess.run(
[
f'{sys.base_exec_prefix}/bin/python',
pathlib.Path(__file__).parent / '_password_box_ui.py',
],
capture_output=True,
)
return process.stdout.rstrip(b'n').decode()

可能不是很优雅,但符合我的目的,即使用IDLE从使用GUI的用户那里获取密码(因此,最终不需要将密码以明文形式存储在任何地方)。

最新更新