By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,675 Members | 2,255 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,675 IT Pros & Developers. It's quick & easy.

Tkinter app structure

P: n/a
Hi there,

I've just started my first project with Tkinter.

I've already coded all the data handling classes and have a nice
interface to work with (it happens to be a wrapper around the DOM of a
large(ish) XML document but thats probably not important ;-)

I'm new to Tkinter so I've started in a fairly random place: the main
menu. I noticed that the event mechanism was based on callbacks so, in a
flash of inspiration, I decided to create a new module called
'commands.py' which would contain all my callback methods (meaning I
could use them for a toolbar as well, if I ever add one) and which acts
as an intermediary between the Tkinter classes and my data hanlding
classes.

I've also created a 'main.py' module which holds the Tk object (called
'root'), the top level data object (called 'data') and the main UI
object (called 'mwnd', an instance of a class inherited from Frame
called 'MainWindow').

* The main.py module imports:

from dataclasses import *
from mainwindow import *
from Tkinter import *

* The mainwindow.py module imports:

from Tkinter import *
from commands import *

* The commands.py modules imports:

import main
import tkMessageBox

* And the dataclasses.py module imports only unrelated modules

This set up should allow me to be able to access main.data and main.root
from the commands.py module and the command callback functions (defined
in commands.py) from mainwindow.py.

main.py looks like this:
====================================
1: from dataclasses import *
2: from mainwindow import *
3: from Tkinter import *
4:
5: data = Database()
6:
7: root = Tk()
8: mwnd = MainWindow(root)
9: root.mainloop()
====================================

However, when I execute it I get the following error:

Traceback (most recent call last):
File "./main.py", line 2, in ?
from mainwindow import *
File "mainwindow.py", line 2, in ?
from commands import *
File "commands.py", line 4, in ?
import main
File "main.py", line 8, in ?
mwnd = MainWindow(root)
NameError: name 'MainWindow' is not defined

(where 'mainwindow.py' line 2 is "from commands import *", commands.py
line 4 is "import main" and the name "MainWindow" is the name of the
class defined in the mainwindow.py module)

Whats going wrong? Is it a 'circular import'? Is there a better way that
I could organise these modules?

Cheers,
Richard
Jul 19 '05 #1
Share this Question
Share on Google+
1 Reply


P: n/a
Richard Lewis wrote:
Hi there,

I've just started my first project with Tkinter. This set up should allow me to be able to access main.data and main.root
from the commands.py module and the command callback functions (defined
in commands.py) from mainwindow.py. <...> Whats going wrong? Is it a 'circular import'? Is there a better way that
I could organise these modules?


Yes, this looks like a circular import to me.

Remember, though, that an import statement in Python isn't completely
analagous to a #include statement in C; because of dynamic typing and
the general guideline of duckitude ("if it walks like a duck and quacks
like a duck..."), you usually don't /need/ to have circular imports.

With the presumption that data = Database() is a mutable object, in
that you interact with it normally and don't reassign it anywhere in
your program, why not just pass data as a parameter to
MainWindow.__init__? Likewise, MainWindow can call commands with
root/data as parameters -- you could even organize your commands into
an instantiated class, and have the CommandClass take both of these as
__init__ arguments. In the program (MUD Client) that I'm working on, I
have a vaguely similar dependency between interface-agnostic backend
code and the in-development TKinter interface; by wrapping everything
except main() and a few constants inside instantiated classes, I think
I've mostly avoided circular imports.

If you really, truly need data to be a global variable, you could
possibly put it inside its own module, and instantiate it via
data_module.data = Database() from main. But that's really ugly, and
I'm not 100% sure that it'd work -- I've never had need to try it, and
am writing this off-the-cuff.

But take this advice all with a lagish grain of iodized NaCl, since I'm
a rank newbie at Python.

Jul 19 '05 #2

This discussion thread is closed

Replies have been disabled for this discussion.