tkinter 消息框的子导入问题
Sub import issues with tkinter messagebox
我正在用 tkinter 编写一个 GUI 应用程序,现在我想使用 tkinter 内置的消息框,所以我想既然我已经导入了 tkinter(作为 tk),那么它就是 tk.messagebox.showerror()
但这或多或少起作用了...
我在通过 IDLE 运行 进行此操作时没有任何问题,但是如果我在终端中使用 python <module-name>.py
它会抛出一个 AttributeError。
这是我能做的最简单的示例:
import tkinter as tk
root = tk.Tk()
tk.messagebox.showerror(title="Test Error", message="This is a test")
root.mainloop()
现在,如果我将 from tkinter import messagebox
添加为导入,则让事情变得更加奇怪,而不是在终端 运行 时使用相同的代码(保留 tk.messagebox.showerror
)。显然它仍然必须被视为 tkinter 的一个属性,那么为什么没有显式导入它就不能工作?
我想我并不是真的在寻找这样的解决方案(因为我找到了使它起作用的方法),而是更多地解释了为什么会发生这种情况。
一如既往地欢迎任何建议!
这个问题之前以 "Why does import tkinter; tkinter.font
works in IDLE but not in python itself?" 的形式出现过,解释是 import
的工作方式与 IDLE 当前如何设置执行代码的子进程之间的交互。
IMPORT:sys.modules 是一个字典,将模块名称映射到导入的模块对象。在较高级别,import modname
等同于以下内容。
if modname not in sys.modules:
sys.modules[modname] = module(modname)
modname = sys.modules[modname]
对于 python 编码的包,模块是从 modname/__init__.py
创建的。导入包不会导入其子模块。也就是说,它没有运行modname/submodule.py
。随后导入子模块会将子模块添加到 sys.modules 并作为属性添加到包中。之后导入模块会将现有模块(具有子模块作为属性)绑定到指定的名称。
IDLE:当前,当 IDLE 为 运行ning 代码设置子进程时,它会直接或间接导入 tkinter 及其子模块。 (代码在idlelib/run.py和它导入的idlelib模块中。)这个可以通过运行ning
看到
for name in sys.modules:
if name.startswith('tkinter'):
print(name)
空闲开始时。所以,当你 运行 import tkinter
时,它是进程中的第二个 tkinter 导入,名称 'tkinter'
绑定到现有的 tkinter 模块,该模块具有子模块作为属性
解决方案:IDLE 的一个目的是开发 运行 在 python 本身中的代码。这是 IDLE 的一个错误 运行 错误代码,不会 运行 在 python 中。我正在研究 refactoring idlelib 以便上面不会打印任何内容。唯一需要的 tkinter 模块是 tkinter.messagebox 并且只有在出现阻止 运行ning 代码的问题时才需要。所以导入messagebox
可以延迟到需要的时候,这种情况很少见。
我正在用 tkinter 编写一个 GUI 应用程序,现在我想使用 tkinter 内置的消息框,所以我想既然我已经导入了 tkinter(作为 tk),那么它就是 tk.messagebox.showerror()
但这或多或少起作用了...
我在通过 IDLE 运行 进行此操作时没有任何问题,但是如果我在终端中使用 python <module-name>.py
它会抛出一个 AttributeError。
这是我能做的最简单的示例:
import tkinter as tk
root = tk.Tk()
tk.messagebox.showerror(title="Test Error", message="This is a test")
root.mainloop()
现在,如果我将 from tkinter import messagebox
添加为导入,则让事情变得更加奇怪,而不是在终端 运行 时使用相同的代码(保留 tk.messagebox.showerror
)。显然它仍然必须被视为 tkinter 的一个属性,那么为什么没有显式导入它就不能工作?
我想我并不是真的在寻找这样的解决方案(因为我找到了使它起作用的方法),而是更多地解释了为什么会发生这种情况。
一如既往地欢迎任何建议!
这个问题之前以 "Why does import tkinter; tkinter.font
works in IDLE but not in python itself?" 的形式出现过,解释是 import
的工作方式与 IDLE 当前如何设置执行代码的子进程之间的交互。
IMPORT:sys.modules 是一个字典,将模块名称映射到导入的模块对象。在较高级别,import modname
等同于以下内容。
if modname not in sys.modules:
sys.modules[modname] = module(modname)
modname = sys.modules[modname]
对于 python 编码的包,模块是从 modname/__init__.py
创建的。导入包不会导入其子模块。也就是说,它没有运行modname/submodule.py
。随后导入子模块会将子模块添加到 sys.modules 并作为属性添加到包中。之后导入模块会将现有模块(具有子模块作为属性)绑定到指定的名称。
IDLE:当前,当 IDLE 为 运行ning 代码设置子进程时,它会直接或间接导入 tkinter 及其子模块。 (代码在idlelib/run.py和它导入的idlelib模块中。)这个可以通过运行ning
看到for name in sys.modules:
if name.startswith('tkinter'):
print(name)
空闲开始时。所以,当你 运行 import tkinter
时,它是进程中的第二个 tkinter 导入,名称 'tkinter'
绑定到现有的 tkinter 模块,该模块具有子模块作为属性
解决方案:IDLE 的一个目的是开发 运行 在 python 本身中的代码。这是 IDLE 的一个错误 运行 错误代码,不会 运行 在 python 中。我正在研究 refactoring idlelib 以便上面不会打印任何内容。唯一需要的 tkinter 模块是 tkinter.messagebox 并且只有在出现阻止 运行ning 代码的问题时才需要。所以导入messagebox
可以延迟到需要的时候,这种情况很少见。