tkinter消息框的子导入问题

时间:2016-02-25 05:22:56

标签: python tkinter messagebox python-idle

我正在用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的一个属性,那么为什么没有显式导入它不能工作呢?

我想我并不是真的在寻找解决方案(因为我找到了一些方法让它发挥作用),但更多地解释了为什么会发生这种情况。

一如既往,欢迎任何建议!

1 个答案:

答案 0 :(得分:1)

此问题之前出现过“为什么import tkinter; tkinter.font在IDLE中有效但在python中无效?”解释是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设置运行代码的子进程时,它直接或间接地导入tkinter及其子模块。 (代码在idlelib / run.py和它导入的idlelib模块中。)这可以通过运行来看到

for name in sys.modules:
    if name.startswith('tkinter'):
        print(name)
当IDLE启动时

因此,当您运行import tkinter时,它是进程中的第二个tkinter导入,名称'tkinter'绑定到将子模块作为属性的现有tkinter模块

解决方案:IDLE的一个目的是开发在python本身运行的代码。 IDLE运行错误的代码是一个错误,无法在python中运行。我正在研究refactoring idlelib,以便上述内容不会打印任何内容。唯一需要的tkinter模块是tkinter.messagebox,只有在出现阻止运行代码的问题时才需要。因此导入messagebox可能会被延迟,直到需要为止,这很少。