12

My understanding is that the standard set-up for a tkinter program starts off like this:

from tkinter import *
from tkinter import ttk

I understand that tkinter is a package, but if I've already imported all with the *, why do I still need to import ttk? Why do I get an error if I take out the second line and try to reference ttk?

temporary_user_name
  • 35,956
  • 47
  • 141
  • 220
  • From what I've found, a single "import tkinter.ttk" seems to be the only thing that produces no warnings in PyDev for Eclipse. – Pat Jan 09 '17 at 01:17

4 Answers4

20

When you do from some_package import *, python will import whatever that package chooses to export. What it chooses to export may be a subset of what is actually stored in the package folder. Why is that? There's no particular reason, it's just how the package author decided to do things.

This information about what to export is defined in the __init__.py file that is inside the package (in this case, tkinter/init.py). If you look at that file you'll notice that it doesn't import ttk itself, thus ttk won't be exported and therefore can't be imported with a wildcard import.

Again, there's no particular reason other than that's how the authors of tkinter and ttk chose to do things.

For more information on the mechanics of packaging, see the packaging portion of the python tutorial (https://docs.python.org/3/tutorial/modules.html#packages)

The better way to import tkinter

You may think it's standard because many tutorials do it that way, but it's generally a bad practice. The better way, IMO, is to give the tkinter library an explicit name:

# python 3.x
import tkinter as tk
from tkinter import ttk 

# python 2.x
import Tkinter as tk
import ttk

This will make your code considerably easier to read, because you have to explicitly state which toolkit you are using:

b1 = tk.Button(...) # uses a standard tk button
b2 = ttk.Button(...) # uses a ttk button

I can think of no good reason to do it any other way. Doing a global import saves you a couple of bytes each time you call a tkinter function, but at the expense of clarity. Plus, it reinforces a bad practice that might bleed into how you use other libraries.

The real authority, IMO, is PEP8, which has this to say on the matter:

Wildcard imports (from import *) should be avoided as they make it unclear which names are present in the namespace, confusing both readers and many automated tools. There is one defensible use case for a wildcard import, which is to republish an internal interface as part of a public API (for example, overwriting a pure Python implementation of an interface with the definitions from an optional accelerator module and exactly which definitions will be overwritten isn't known in advance).

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
5

Because tkinter/__init__.py doesn't import ttk, so ttk isn't included in from tkinter import *.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
1

Briefly: from tkinter import * imports from file/packet tkinter but it doesn't mean that it will import from file/packet tkinter.ttk

furas
  • 134,197
  • 12
  • 106
  • 148
-1

what the other two answers here failed to state is that ttk is not imported because it is a submodule within the tkinter module, effectively a module in itself.

so when you import tkinter you get all of the parts that directly belong to tkinter

but ttk does not directly belong and so must be imported explicitly.

however Bryan Oakley makes a good point that importing everything from a module into local namespace (as many newbies do) can lead to big problems later on when you start to use more modules. this is because some of these modules may share function names even though the functions themselves may do completely different things.

it is always best for large modules to do:

import module as mod

or

import module

and then reference the functions as belonging to the modules namespace:

module.function()

this gives you more control over what you are doing and makes it clearer later on what the function actually belonged to.

James Kent
  • 5,763
  • 26
  • 50