Noob question about import

What am I doing wrong here, please?

My understanding was that from <module> import * means “please give me access everything in that module that I’m meant to have access to”

Am I wrong?

The reason for my question is this code that I’ve written, as a small tester for learning.

#!/usr/bin/python3

from tkinter import *
from tkinter.ttk import *

# -------------For the 'About' function----------------#
from tkinter import messagebox
#?? Why do I need this, when I've got the import * above??##

def about():
    messagebox.showinfo('About','This is only a test.')
#------------------------------------------------------#

#---------------For the File dialog Box----------------#
from tkinter import filedialog
#?? Why do I need this, when I've got the import * above??##

def openfile():
    filename = filedialog.askopenfilename()
    print(filename)
#------------------------------------------------------#

#-----------------------Mainloop-----------------------#
root = Tk()
root.title('My First Application')
root.geometry('1200x600')
root.resizable(False, False)

# Creating Menubar
menubar = Menu(root)

# Adding File Menu
file = Menu(menubar, tearoff = 0)
menubar.add_cascade(label = 'File', menu = file)

# Add items to the File Menu
file.add_command(label = 'New File', command = None)
file.add_command(label = 'Open...',  command = openfile)
file.add_command(label = 'Close',    command = None)
file.add_command(label = 'Save',     command = None)
file.add_command(label = 'Exit',     command = root.destroy)

help = Menu(menubar, tearoff = 0)
menubar.add_cascade(label = 'Help', menu = help)

help.add_command(label = 'About', command = about)

# Display Menu
root.config(menu = menubar)

# Run the app
root.mainloop()

You’ll notice that, as comments, I’ve asked the question: Why do I need this, when I’ve got the import * above. I’ve had to insert the line of code above said comments, for the app to work, but I can’t see why, given the code at lines 3 & 4.

I’ve been as proactive on this as I can, that is to say, I’ve not simply hit a wall and then posted right away; I’ve been searching for an answer to this for the past 6 hours, so I’ve concluded that there has to be a fundamental gap in my knowledge, which means I don’t know what to search for.

messagebox and filedialog are not attributes of the tkinter module, which is why they are not available when you do from tkinter import *.

Instead, they are submodules of tkinter. Submodules such as messagebox can be imported via import tkinter.messagebox or from tkinter import messagebox.

See this documentation for more details.

1 Like

Thank you.

So maybe it would be better if line 3 reads…
from tkinter import (Tk, messagebox, filedialog, Menu)
… for cleaner code, do you think? Or would I run into issues with that approach?

Generally, using import * is discouraged because it brings a lot of variables into your namespace.

Using
from tkinter import Tk, messagebox, filedialog, Menu
would be better. Note that the parentheses are not necessary. Just make sure that you edit this line if you need something else from tkinter later on.

Your help is very much appreciated.

Have a good day and be safe.

Peace.

What I personally do for Tk is the following:

from tkinter import ttk, messagebox, filedialog
import tkinter as tk

Then you can access tk.Label, ttk.Label etc and they don’t clutter your global namespace. If you want to have the various HORIZONTAL etc constants, do from tkinter.constants import *.

Thanks for your input.

I have a question about your code:
In my notes I have it that the import commands need to be in a specific order…

from tkinter import *
from tkinter import ttk

… otherwise the the basic Tk widgets will not be overwritten by the ttk ones.

So, (I’ve yet to try this, but…) going back to my ‘one liner’, I’d use:

from tkinter import Tk, messagebox, filedialog, Menu, ttk

ttk being at the end, thus being the last to be imported and overwriting the basic Tk widgets.

As I say, I’ve yet to try this, but the logic is good, right?

I’m also unhappy with the look of the menu bar and as it turns out, it’s simply the way it is; no ttk alternative. But there is a ttk.Button etc and as such I can see no issues with building a custom menu bar, with the nicer looking ttk widgets. This also gives the option of placing said menu bar in anywhere; Top, Bottom, LHS, RHS, or even have it pop up as and when it’s needed.
Your thoughts?

{update}
from tkinter import Tk, messagebox, filedialog, Menu, Label, ttk

… works fine. Also the position of ttk in that line of code, seems to make no difference.

The order of imports is only going to matter if you’re using from x import, because that puts the objects directly as global variables. When you did ... import * for both, the second one overwrites the globals the first assigned which is why it breaks. Doing import tkinter as tk just assigns tk, so they don’t conflict.

Think of import as first loading the module, then doing some assignments:

import tkinter # tkinter = ...
import tkinter as tk # tk = ...
from tkinter import Menu  # Menu = ...
from tkinter import *  # Lots of assignments
 # Tk = ...
 # Menu = ...
 # Frame = ... 
1 Like

Sound, thank you :slight_smile:

Also, as @TeamSpen210 alluded to, instead of using from imports, you can also use regular absolute imports and in your code, specify the fully qualified names of objects, which helps you keep track of exactly where everything came from, avoid any issues with name clashes and not have to add a new item to your imports to use an existing name from a module you’ve already imported. On the other hand, it is more verbose and doens’t list the names you’re using up top, so some prefer one and some the other.

So, you could do something like:

import tkinter
import tkinter.messagebox
import tkinter.ttk

tkinter.messagebox.showinfo(...)
tkinter.Menu(...)
tinker.ttk.Label(...)
1 Like

Thanks for the advice. I think each has it’s own merits:

For my humble little project, a one line import keeps the code simple, sparse and readable.

If I were to develop much deeper code or even collaborate on a project, then a more verbose, complex approach would be better.