#python
Несколько раз встречал упоминание о том, что выполнение кода при импортировании модуля- плохая практика. При этом, я не смог нигде найти объяснений этому утверждению. Вопроса два. Первый: почему выполнение кода при импорте модуля, считается плохой практикой? Второй: что считать выполнением кода, в контексте данного утверждения? Присваивание значений глобальным переменным, выполнение функций или что-то еще? Ведь определение классов и функций в данном модуле, так-же как и импорт других модулей (в данном модуле, который мы импортируем), ведь это тоже можно считать "выполнением кода"?
Ответы
Ответ 1
Я бы не сказал, что это прям-таки вообще плохая практика, просто нужно подходить к этому делу с умом, понимать, чем это чревато, пользоваться этим не бездумно. Причины ограничивать это дело, если подумать, мне видятся следующие: Явное лучше неявного. Вы теряете контроль над тем, когда именно будет выполнен данный код, а это может оказаться важным. Модули в Python можно импортировать не только на верхнем уровне, но и внутри функции или метода, а это значит, что код модуля будет выполнен не во время старта приложения, а во время запуска такой функции и выполнения в ней инструкции import. Функций, импортирующих модуль, к тому же может оказаться не одна, и какая из них и когда выполняется первой в вашем огромном приложении, может быть совсем неочевидным. Несмотря на то, что код модуля выполняется единожды при первой загрузке (собственно при последующих импортах он даже не загружается), сделать так, чтоб он выполнился не один раз не так уж и сложно. Хороший пример (не единственная возможность сделать так) рассматривается вот тут. Ваш код будет повторно выполняться при перезагрузке вашего модуля с помощью reload, что так же может оказаться нежелательным, если у этого кода есть определенные сайд-эффекты. Этот код может выполняться долго, что повлечет за собой замедление загрузки модуля и, как следствие, запуска приложения. При этом, хочу заметить, что вообще эта возможность (в умеренных количествах) используется повсеместно, и, в умеренных опять же количествах, в большинстве случаев проблем не доставляет. Например декоратор функции -- это выполнение пользовательского кода во время загрузки модуля. Хотя, если декоратор не просто "изменяет" декорируемую функцию, а имеет сайд-эффекты, это может быть (но далеко не обязательно будет) источником проблем, если вы не понимаете всех этих механизмов. По второму же вопросу, присваивания значений (а не результатов вызовов пользовательских функций) глобальным переменным, создание функций и классов, импорт других модулей, то есть, в некотором роде, декларативный код (вызывающий выполнение не вашей пользовательской логики, а логики интерпретатора), в контексте данного утверждения выполнением кода не считается. В общем мораль в том, что нужно просто четко понимать возможные последствия выполнения кода при импорте модуля в Python, и пользоваться этой возможностью разумно. Изначальное высказывание о недопустимости этого сродни высказыванию о том, что goto есть абсолютное зло. Да, бездумное использование чревато огромными проблемами, но при этом в том же ядре Linux goto для тех вещей, где оно действительно уместно, используется повсеместно.Ответ 2
Все нижеследующее - мое личное мнение. Если в вашем модуле есть код, который при импортировании не должен выполняться, но он выполняется - это плохо. Нужно выносить его в блок if __name__ == '__main__'. Хотя, если это не модуль, а просто одноразовый скрипт, который не придется куда-то подключать, то и задумываться о вероятном импортировании файла в качестве модуля незачем. Если в модуле есть код, который при импортировании выполняется, и это так и задумано, то не вижу в этом ничего плохого. Тем более, что фактически весь код модуля при импортировании выполняется (в том числе и определения классов и функций фактически выполняются в рантайме, т.к. язык интерпретируемый), так что не вижу смысла вообще избегать, к примеру, инициализации переменных или выполнения произвольного кода при импортировании.
Комментариев нет:
Отправить комментарий