从文件导入类时,会导入确保模块(特定于tkinter)

时间:2014-12-16 05:31:09

标签: python tkinter

我希望在MVC模式中将以下代码放在自己的文件(view.py)中。我将有一个初始化对象的控制器,然后调用main函数:

from view import GUI
gui = GUI()
gui.main()

然后GUI类确保正确导入tkinter以便它可以绘制gui。就目前而言,尝试运行控制器代码会导致以下错误:

> python controller.py
trying to load Tkinter
loading Tkinter failed, trying tkinter instead
Loading gui
main method
Traceback (most recent call last):
  File "controller.py", line 9, in <module>
    gui.main()
  File "[...]\view.py", l
ine 31, in main
    self.root = TK.Tk()
NameError: name 'TK' is not defined

这是view.py:

class GUI:
    #import Tkinter # no underscore, uppercase 'T' for versions prior to V3.0
    #import tkinter # no underscore, lowercase 't' for V3.0 and later
    try:
        print("trying to load Tkinter")
        TK = __import__(Tkinter)
    except:
        print("loading Tkinter failed, trying tkinter instead")
        TK = __import__("tkinter")
    #from tkinter import N, S, E, W, END


    def __init__(self):
        print("Loading gui")

    def main(self):
        print("main method")
        # Tk root widget: window with titlebar, etc
        self.root = TK.Tk()

        # Tk buttons frame (left hand side)
        buttonsFrame = TK.Frame(self.root)
        buttonsFrame.grid(row=0, column=0, sticky=TK.N+TK.S+TK.E+TK.W)

        # Tk buttons:
        self.buttonLoad = TK.Button(buttonsFrame, text="Load Recipes", command=self.actionLoad)
        #more buttons
        self.buttonLoad.grid(row=0, column=0, sticky=TK.N+TK.S+TK.E+TK.W)
        #loading more buttons

        self.root.mainloop()


    def actionLoad(self):
        print("\"Load Recipes\" pressed")

我担心这部分问题是由于缺乏对oop和python哲学的某种组合的理解,但我很高兴能够接受这两种教学。

我希望将tkinter加载为类变量而不是实例变量会使其更容易解决,但这似乎没有成功。

编辑:这是似乎正确运行的更新后的view.py

try:
    print("trying to load Tkinter")
    import Tkinter as TK
    from Tkinter import N, S, E, W, END
except ImportError:
    print("loading Tkinter failed, trying tkinter instead")
    import tkinter as TK
    from tkinter import N, S, E, W, END



class GUI:
    #import Tkinter # no underscore, uppercase 'T' for versions prior to V3.0
    #import tkinter # no underscore, lowercase 't' for V3.0 and later

    #from tkinter import N, S, E, W, END


    def __init__(self):
        print("Loading gui")

    def main(self):
        print("main method")
        # Tk root widget: window with titlebar, etc
        self.root = TK.Tk()

        # Tk buttons frame (left hand side)
        buttonsFrame = TK.Frame(self.root)
        buttonsFrame.grid(row=0, column=0, sticky=N+S+E+W)

        # Tk buttons:
        self.buttonLoad = TK.Button(buttonsFrame, text="Load Recipes", command=self.actionLoad)
        self.buttonAdd = TK.Button(buttonsFrame, text="Add Recipe", command=self.actionAdd)
        self.buttonModify = TK.Button(buttonsFrame, text="Modify Recipe", command=self.actionModify)
        self.buttonRemove = TK.Button(buttonsFrame, text="Remove Recipe", command=self.actionRemove)
        self.buttonQuit = TK.Button(buttonsFrame, text="Quit", command=self.actionQuit)
        # have to assign the layout via grid later because .grid doesn't return a type which messes up stuff like .insert()
        self.buttonLoad.grid(row=0, column=0, sticky=N+S+E+W)
        self.buttonAdd.grid(row=1, column=0, sticky=N+S+E+W)
        self.buttonModify.grid(row=2, column=0, sticky=N+S+E+W)
        self.buttonRemove.grid(row=3, column=0, sticky=N+S+E+W)
        self.buttonQuit.grid(row=4, column=0, sticky=N+S+E+W)

        # Tk recipe listbox (b/c of TK.EXTENDED, it supports selection of any combination of entries)
        self.recipeList = TK.Listbox(self.root, selectmode=TK.EXTENDED)
        # have to assign the layout via grid later because .grid doesn't return a type which messes up stuff like .insert()
        self.recipeList.grid(row=0, column=2, sticky=N+S+E+W, rowspan=10, columnspan=10)
        # populate listbox
        for option in range(0,5):
            self.recipeList.insert(TK.END, "option " + str(option))





        self.root.mainloop()

    def actionLoad(self):
        print("\"Load Recipes\" pressed")
        return "load"
    def actionAdd(self):
        print("\"Add Recipe\" pressed")
        return "add"
    def actionRemove(self):
        print("\"Remove Recipe\" pressed")
        return "remove"
    def actionModify(self):
        print("\"Modify Recipe\" pressed")
        return "modify"
    def actionQuit(self):
        quit()

1 个答案:

答案 0 :(得分:2)

原始代码抛出NameError关于&#39; TK&#39;未定义的是您将其导入类(静态)变量。因此,要使原始代码正常工作,请执行以下操作:

  • 使用类名称对变量的使用进行前缀,将TK替换为GUI.TK,无论在哪里使用(请参阅下面此答案的评论中的讨论)。
  • 或者将类外的try...except块移到包含该类的模块中,方法是将其放在view.py文件的顶部(参见问题评论中的讨论)。

但是,我认为你应该避免使用__import__(文档说&#34;这是日常Python编程中不需要的高级函数&#34;)。请尝试以下方法:

try:
    print("trying to load Tkinter")
    import Tkinter as TK
except ImportError:
    print("loading Tkinter failed, trying tkinter instead")
    import tkinter as TK

您可以将上面的块放在类中,就像之前一样(在这种情况下使用GUI.TK无处不在),或者在模块中的类之外。我认为您应该将导入放在文件的顶部,就像您在更新的帖子中所做的那样(PEP 8建议&#34;导入始终放在文件的顶部&#34;)。

另请注意ImportError的使用。最好在此处捕获特定的异常,而不是捕获所有异常(请参阅https://wiki.python.org/moin/HandlingExceptions中的&#34;常规错误捕获&#34;部分)。