Comments 31
Explicit is better than implicit.
Поэтому пока вижу использование этой либки в основном в проектах с устоявшимися правилами именования. В этом случае это правило не будет нарушаться, поскольку автоматизация импортов станет просто реализацией уже существующего порядка (или таки будет нарушаться, но не так сильно, в зависимости от философской позиции :-) ).
Плюс, для быстрого написания одноразового кода тоже удобно.
А как насчёт работы линтеров? flake8, pylint? Уживаются ли они с библиотекой?
Определённые проблемы с линтерами и автодополнением в IDE я ожидаю. Буду их решать по мере поступления сообщений об ошибках.
Основную проблему уже обозначили выше — такой подход ломает любой линтинг и автокомплит, что, собственно, безумно плохо.
Как в данном случае либа будет сочетаться с IDE?
А как решается проблема "откуда это взялось?" при чтении исходного кода?
Нет, это вы отвечаете на вопрос "как этот модуль тут появился". А у меня другой вопрос — "откуда это взялось"?
Если у меня в коде написано queue.Empty — это локальная переменная которую кто-то где-то инциализировал или это модуль? А если у меня есть переменная chunk и я забыл её проинциализировать, а вы мне любезно туда chunk модуль подсунули? За что?
Нет, это вы отвечаете на вопрос «как этот модуль тут появился». А у меня другой вопрос — «откуда это взялось»?
Приведите пример в котором ответ на ваш вопрос не даётся просмотром импортов. Пока я не понимаю что вы хотите сказать.
Если у меня в коде написано queue.Empty — это локальная переменная которую кто-то где-то инициализировал или это модуль? А если у меня есть переменная chunk и я забыл её проинициализировать, а вы мне любезно туда chunk модуль подсунули? За что?
Для этого в проекте должно совпасть несколько довольно критичных ошибок:
— Должно случиться пересечение имён модулей и переменных.
— Функциональность не должна быть покрыта ни одним тестом (либо тесты не запускаются).
— Должен быть написан кривой код.
Если такое случается чаще раза в год, то на проекте проблемы совсем другого рода и, действительно, играться с метапрограммированием команде не стоит.
Сейчас в Python идёт движение за то, чтобы модуль выглядел как обычный объект. Добавляются разные технические методы для эмулирования этого. Например есть PEP-0562 То есть с точки зрения кода должно быть без разницы что в переменной находится (модуль, функция, обычный объект), пока эта сущность предоставляет нужный интерфейс.
Плюс, разносить объявление переменной и её использование на несколько экранов (а именно в этом случае нельзя сказать что в ней) — моветон. Не надо так делать.
Как одной строчкой сломать/отключить работу в любой IDE autocomplete, linter'ов, функций рефакторинга, статических анализаторов типов и т.д. Список можно продолжать. Не говоря о невозможности использовать условные импорты.
Из доступных правил не получится сделать так:
try:
import loads from ujson as json_loads
except ImportError:
import loads from json as json_loads
import smart_imports
smart_imports.all()
try:
from ujson import loads as json_loads
except ImportError:
from json import loads as json_loads
json_data = '{"x": 1}'
parsed_data = json_loads(json_data)
parsed_data['y'] = math.pi
print(parsed_data)
# {'x': 1, 'y': 3.141592653589793}
А если очень надо, то и правило написать не сложно. Только оно не надо скорее всего, поскольку усовный импорт должен только в одном месте делаться.
я как-то пробовал отлаживать плюсовый код с примерно тысячей модулей. после открытого примерно 30-го файла по колл-стэку я окончательно потерялся.
Касательно моего проекта. В вебе есть есть определённые соглашения по организации кода. Например, фреймворк Django рекомендует отдельно описывать схему базы, структуру url и прочее для каждого компонента. Это приводит к появлению файлов с небольшим количеством кода, но засчёт правильного разделения кода по модулям это в итоге удобно.
from all_libs import *
Без магии и инструментарий не поломается.— Циклические зависимости вылезут во всей красе.
— В случае компонентов, организованных по одному шаблону, нельзя будет обратиться к соседнему модулю по имени (так как оно пересечётся с таким же именем в другом компоненте). То есть вопрос импортов полностью не закроется.
— Время запуска будет максимльным из возможного, так как вообще всё придётся импортировать.
А как у вас оно решается, когда нужны 2 модуля которые цыклический друг от друга?
2. Такие импорты делать класический или по полному пути компонента, либо аналогично сделать локальный модуль импорта.
3. Если проект стартует целиком и эти модули импортируются в любом случае (монолит), то разницы не будет.
А если нужна возможность запуска кусками, то можно сделать «режимы запуска» где будет импортироваться не все.
Ещё как вариант не импортировать глобально, а как один модуль, и использовать, например, как
libs.math.sqrt
, тогда можно вообще сделать ленивую подгрузку модулей.Так же можно комбинировать подходы, и ложить в общий импорт только то, что действительно используется часто, тогда кол-во импортов скоратится до минимума.
Кроме того есть и другие архитектурные решения, где минимум импортов в больших проектах.
from {что-то} import *
использовать вовсе плохая практика, хоть питон и позволяет, да.В комментариях пишут про недостатки и со многим могу согласиться, но все-таки это красиво! В качестве решения проблемы с тулами может быть можно сделать двухэтапный вариант, когда тул генерирует список импортов и сохраняет в файл, который уже явно импортируется далее по тексту. Тогда ругань тулов будет только на свежедобавленные импорты до первого запуска.
потом добавили «типизацию»
теперь сделаем неявный импорт
потом что добавим?
PyCharm же всё автоматически добавляет, зачем ещё какую-то магию городить?
Автоматизация импортов в Python