Страницы

Поиск по вопросам

суббота, 13 октября 2018 г.

Выполнение кода при импорте модуля в Python- плохая практика?

Несколько раз встречал упоминание о том, что выполнение кода при импортировании модуля- плохая практика. При этом, я не смог нигде найти объяснений этому утверждению. Вопроса два.
Первый: почему выполнение кода при импорте модуля, считается плохой практикой?
Второй: что считать выполнением кода, в контексте данного утверждения? Присваивание значений глобальным переменным, выполнение функций или что-то еще? Ведь определение классов и функций в данном модуле, так-же как и импорт других модулей (в данном модуле, который мы импортируем), ведь это тоже можно считать "выполнением кода"?


Ответ

Я бы не сказал, что это прям-таки вообще плохая практика, просто нужно подходить к этому делу с умом, понимать, чем это чревато, пользоваться этим не бездумно.
Причины ограничивать это дело, если подумать, мне видятся следующие:
Явное лучше неявного. Вы теряете контроль над тем, когда именно будет выполнен данный код, а это может оказаться важным. Модули в Python можно импортировать не только на верхнем уровне, но и внутри функции или метода, а это значит, что код модуля будет выполнен не во время старта приложения, а во время запуска такой функции и выполнения в ней инструкции import. Функций, импортирующих модуль, к тому же может оказаться не одна, и какая из них и когда выполняется первой в вашем огромном приложении, может быть совсем неочевидным. Несмотря на то, что код модуля выполняется единожды при первой загрузке (собственно при последующих импортах он даже не загружается), сделать так, чтоб он выполнился не один раз не так уж и сложно. Хороший пример (не единственная возможность сделать так) рассматривается вот тут Ваш код будет повторно выполняться при перезагрузке вашего модуля с помощью reload, что так же может оказаться нежелательным, если у этого кода есть определенные сайд-эффекты. Этот код может выполняться долго, что повлечет за собой замедление загрузки модуля и, как следствие, запуска приложения.
При этом, хочу заметить, что вообще эта возможность (в умеренных количествах) используется повсеместно, и, в умеренных опять же количествах, в большинстве случаев проблем не доставляет. Например декоратор функции -- это выполнение пользовательского кода во время загрузки модуля. Хотя, если декоратор не просто "изменяет" декорируемую функцию, а имеет сайд-эффекты, это может быть (но далеко не обязательно будет) источником проблем, если вы не понимаете всех этих механизмов.
По второму же вопросу, присваивания значений (а не результатов вызовов пользовательских функций) глобальным переменным, создание функций и классов, импорт других модулей, то есть, в некотором роде, декларативный код (вызывающий выполнение не вашей пользовательской логики, а логики интерпретатора), в контексте данного утверждения выполнением кода не считается.
В общем мораль в том, что нужно просто четко понимать возможные последствия выполнения кода при импорте модуля в Python, и пользоваться этой возможностью разумно. Изначальное высказывание о недопустимости этого сродни высказыванию о том, что goto есть абсолютное зло. Да, бездумное использование чревато огромными проблемами, но при этом в том же ядре Linux goto для тех вещей, где оно действительно уместно, используется повсеместно.

Комментариев нет:

Отправить комментарий