Почему после "import tkinter", могу обратиться "tkinter.Tk()", но не могу обратиться "tkinter.ttk"?

Рабочий код. Python 3.10.0 на виндовс.

import tkinter
from tkinter import ttk
mainWindow = tkinter.Tk()
area = ttk.Frame(mainWindow, padding=10)
mainWindow.mainloop()

Из второй строки следует что имя "ttk" является атрибутом модуля "tkinter" так же как имя "Tk". Однако обращение "tkinter.ttk" не работает:

import tkinter
mainWindow = tkinter.Tk()
area = tkinter.ttk.Frame(mainWindow, padding=10)
mainWindow.mainloop()

Traceback (most recent call last): File "C:\Users\room7364\Documents\pyprogs\tkinterTry\importTtkQuestUnworking.py", line 3, in area = tkinter.ttk.Frame(mainWindow, padding=10) AttributeError: module 'tkinter' has no attribute 'ttk'

Если "ttk" не является атрибутом "tkinter", то почему тогда работает "from tkinter import ttk" ?


Ответы (1 шт):

Автор решения: asagorik

Это зависит от того, написан ли импорт модулей в библиотечных __init__.py файлах.

Похожий вопрос и ответ на него: https://stackoverflow.com/a/60315893/
Цитирую оттуда пример, иллюстрирующий в каких случаях такой импрот срабатывает и в каких не срабатывает:

.
├── __init__.py
├── main.py
├── numpy
│   ├── __init__.py
│   └── random
│       ├── __init__.py
│       └── mtrand.py
└── tkinter
    ├── __init__.py
    └── ttk.py
#numpy/__init__.py:
from .random import RandomState
#numpy/random/__init__.py:
from .mtrand import RandomState
#numpy/random/mtrand.py:
class RandomState:
    pass

#tkinter/__init__.py:
#tkinter/ttk.py:
class Spinbox:
    pass

#__init__.py:
#main.py:
import numpy
import tkinter

print(numpy.random.RandomState)

try:
    print(tkinter.ttk.Spinbox)
except AttributeError:
    print("Caught an exception!")
    import tkinter.ttk
    print(tkinter.ttk.Spinbox)

Вывод:

<class 'numpy.random.mtrand.RandomState'>
Caught an exception!
<class 'tkinter.ttk.Spinbox'>
→ Ссылка