Импорт в Питоне объединяет две операции:
- найти (загрузить и проинициализировать) модуль
- ввести новые имена в текущем окружении (как операция присваивания
=)
Почему и как срабатывает команда from app import app?
from module import name импортирует module модуль и если он не содержит name имя, то происходит попытка импортировать module.name модуль. Если name уже существует, то name модуль не импортируется, а просто аналог name = module.name исполняется.
В коде, представленном в вопросе, app имя уже существует в app модуле поэтому просто импортируется модуль app и в текущем пространстве имён новое имя создаётся (аналог: app = __import__('app').app).
Почему в данном случае объект app класса flask нормально импортируется из пакета app, хотя и не является модулем?
Все имена, присвоенные в app/__init__.py, доступны как app.имя после импорта app пакета (import app).
app.app уже доступен, поэтому не происходит попытки импортировать app.app модуль. Если удалить app = ... из __init__.py, то произойдёт попытка импорта app.app модуля.
Рекомендуется app = Flask(__name__) внутрь функции create_app(...) помещать, чтобы можно было разные параметры передавать (например, для тестов).
При попытке определить объект app, например, в views.py, он уже не импортируется.
Вложенные модули неявно не импортируются (from app import app) не импортирует views.py модуль. Если views.py содержит name = 'value', то чтобы импортировать name имя в run.py следует написать:
from app.views import name
Если есть желание углубиться, то все детали системы импорта описаны в спецификации Питона.