its not a bug. Its the way tkinter is packaged.
When you just
import tkinter, python looks for a tkinter.py file or a tkinter directory. If it is a directory, it looks for a __init__.py file in that directory. The __init__.py file then is put in your namespace. If you grep the class headers of that init file, you will see familiar class names.
metulburr@ubuntu:/usr/lib/python3.5/tkinter$ cat __init__.py | grep class
Tkinter provides classes which allow the display, positioning and
class Event:
using bind, bind_all, bind_class, or tag_bind, the callback is
class Variable:
Subclasses StringVar, IntVar, DoubleVar, BooleanVar are specializations
return self.__class__.__name__ == other.__class__.__name__ \
class StringVar(Variable):
class IntVar(Variable):
class DoubleVar(Variable):
class BooleanVar(Variable):
class Misc:
"""Internal class.
Base class which defines methods common for interior widgets."""
def option_get(self, name, className):
return self.tk.call('option', 'get', self._w, name, className)
def winfo_class(self):
"""Return window class name of this widget."""
return self.tk.call('winfo', 'class', self._w)
def bind_class(self, className, sequence=None, func=None, add=None):
return self._bind(('bind', className), sequence, func, add, 0)
def unbind_class(self, className, sequence):
self.tk.call('bind', className , sequence, '')
self.__class__.__module__, self.__class__.__qualname__, self._w)
class CallWrapper:
"""Internal class. Stores function to call when some user
class XView:
"""Mix-in class for querying and changing the horizontal position
class YView:
"""Mix-in class for querying and changing the vertical position
class Wm:
class Tk(Misc, Wm):
def __init__(self, screenName=None, baseName=None, className='Tk',
is the name of the widget class."""
self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
self.readprofile(baseName, className)
def readprofile(self, baseName, className):
class_tcl = os.path.join(home, '.%s.tcl' % className)
class_py = os.path.join(home, '.%s.py' % className)
if os.path.isfile(class_tcl):
self.tk.call('source', class_tcl)
if os.path.isfile(class_py):
exec(open(class_py).read(), dir)
# Ideally, the classes Pack, Place and Grid disappear, the
# pack/place/grid methods are defined on the Widget class, and
# Pack, Place or Grid class, so I leave them intact -- but only as
# the Misc class (which now incorporates all methods common between
# copied into the Pack, Place or Grid class.
def Tcl(screenName=None, baseName=None, className='Tk', useTk=0):
return Tk(screenName, baseName, className, useTk)
class Pack:
Base class to use the methods pack_* in every widget."""
class Place:
Base class to use the methods place_* in every widget."""
class Grid:
Base class to use the methods grid_* in every widget."""
class BaseWidget(Misc):
"""Internal class."""
classes = [(k, v) for k, v in cnf.items() if isinstance(k, type)]
for k, v in classes:
for k, v in classes:
class Widget(BaseWidget, Pack, Place, Grid):
"""Internal class.
Base class for a widget which can be positioned with the geometry managers
class Toplevel(BaseWidget, Wm):
Valid resource names: background, bd, bg, borderwidth, class,
for wmkey in ['screen', 'class_', 'class', 'visual',
class Button(Widget):
class Canvas(Widget, XView, YView):
class Checkbutton(Widget):
class Entry(Widget, XView):
class Frame(Widget):
Valid resource names: background, bd, bg, borderwidth, class,
if 'class_' in cnf:
extra = ('-class', cnf['class_'])
del cnf['class_']
elif 'class' in cnf:
extra = ('-class', cnf['class'])
del cnf['class']
class Label(Widget):
class Listbox(Widget, XView, YView):
class Menu(Widget):
class Menubutton(Widget):
class Message(Widget):
class Radiobutton(Widget):
class Scale(Widget):
class Scrollbar(Widget):
class Text(Widget, XView, YView):
class _setit:
"""Internal class. It wraps the command in the widget OptionMenu."""
class OptionMenu(Menubutton):
class Image:
"""Base class for images."""
class PhotoImage(Image):
class BitmapImage(Image):
class Spinbox(Widget, XView):
class LabelFrame(Widget):
background, class, colormap, container,
class PanedWindow(Widget):
These are the most used. However not everything is in there. As you can see from
metulburr@ubuntu:/usr/lib/python3.5/tkinter$ ls
colorchooser.py dialog.py font.py messagebox.py simpledialog.py
commondialog.py dnd.py __init__.py __pycache__ tix.py
constants.py filedialog.py __main__.py scrolledtext.py ttk.py
the only one of these that are imported into __init__.py file are the constants file here
metulburr@ubuntu:/usr/lib/python3.5/tkinter$ cat __init__.py | grep import
import tkinter
from tkinter.constants import *
import sys
import _tkinter
from tkinter.constants import *
import re
import warnings
import os
import os
exec('from tkinter import *', dir)
import traceback
import warnings
everything else will need a separate import.
You can remedy the fact of importing each sub-module individually by importing all with star imports, but
that is not a good idea.
Instead of
from tkinter.filedialog import askopenfilename
you can just do
from tkinter import filedialog
then if you need more dialogs in that module you dont need to import each one.