When do we need both import * and import a particular function or module?

from tkinter import *
from tkinter import ttk
Doesnt import * imports ttk as well?

By KR411-prog via Discussions on Python.org at 08Jul2022 18:29:

from tkinter import *
from tkinter import ttk
Doesnt import * imports ttk as well?

You would need to test that.

>>> from tkinter import *
>>> ttk
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'ttk' is not defined

so yes, you need to import ttk specificly.

Note that in general we don’t use import * very much. It is more
common to import just specific names you want. Consider code like this:

from A import *
from B import *

If both of these define the same name (with different meanings of
course), now you don’t know what that conflicting name means. (Well, if
you know the name is defined in both A and B, you’ve got the B
version because that happenned second. But if you don’t know that, a
name may have come from A or B depending who defined it.)

To my mind the only sane time to import * is when writing code which
is primarily using one module with many names inside it. Example:

from tkinter import *

where you’re writing GUI code, and will import other things you need
with specific names. Then it makes a lot of sense. But I’d always
structure that like:

from tkinter import *
... all the other imports _after_ this ...

That way if there’s a name conflict then you know that the name came
from tkinter, unless you specificly imported the name in a later
import:

from tkinter import *
from my_widgets import Button  # my better Button widget

Thus Button is reliably my_widgets.Button and not tkinter.Button.
If they were the other way around, you might import something specific
and have it replaced by a tkinter import.

from my_widgets import ObscureWidget
from tkinter import *

Now ObscureWidget might mean tkinter.ObscureWidget if tkinter
just happens to provide that name. Ouch.

Now: why didn’t you get ttk?

Importing * imports all the published names from a module/package.
The default is all names not beginning with an underscore, but a module
might tune that by defining the __all__ list to be an specific list of
names.

Have a read here:

speciificly the part a few paragraphs down under the examples which
says:

If the list of identifiers is replaced by a star (‘*’), all public
names defined in the module are bound in the local namespace for
the scope where the import statement occurs.

The public names defined by a module are determined by checking
the module’s namespace for a variable named all; if defined,
it must be a sequence of strings which are names defined or
imported by that module. The names given in all are all
considered public and are required to exist. If all is not
defined, the set of public names includes all names found in the
module’s namespace which do not begin with an underscore character
(‘_’). all should contain the entire public API. It is intended
to avoid accidentally exporting items that are not part of the
API (such as library modules which were imported and used within
the module).

Cheers,
Cameron Simpson cs@cskk.id.au

1 Like

We do not recommend using star imports very often, only for modules which are designed to be used that way. tkinter is one of those, but even there, many people argue that it is better to use

import tkinter as tk
btn = tk.Button( ... )

than

from tkinter import *
btn = Button( ... )

Even though it takes three extra characters to type, it is easier to tell where Button came from with the tk.Button version.

If you try it, you will see that import * does not import ttk, because it is not listed in tkinter.__all__

'ttk' in tk.__all__  # returns False

I suppose that is deliberate, but I don’t know why.

3 Likes

Thankyou very much for the responses…Its clear now