2010-11-14 5 views
28

Иногда я хочу, чтобы загрузка ленивого модуля в Python. Обычно, потому что я хочу, чтобы требования времени выполнения или время запуска были низкими и разделение кода на подмодули было бы громоздким. Типичный случай использования и моя предпочтительная в настоящее время реализация этого:Лучшая практика для ленивой загрузки модулей Python

jinja2 = None 

class Handler(...): 
    ... 
    def render_with_jinja2(self, values, template_name): 
     global jinja2 
     if not jinja2: 
      import jinja2 
     env = jinja2.Environment(...) 
     ... 

Интересно: есть ли канонический/лучший способ реализации ленивой загрузки модуля?

+0

Другой причиной ленивой загрузки может быть то, что это плохо написанный сторонний модуль, который зависит от параметров глобальной среды, которые необходимо изменить перед импортом. (Конечно, эти модули очень интересны.) – jpmc26

ответ

45

У вас нет причин для отслеживания импорта вручную - виртуальная машина поддерживает список модулей, которые уже были импортированы, и любые последующие попытки импортировать этот модуль приводят к быстрому поиску dict в sys.modules и ничего остальное.

Разница между кодом и

def render_with_jinja2(self, values, template_name): 
    import jinja2 
    env = jinja2.Environment(...) 

равна нулю - когда мы попали, что код, если jinja2 не был импортирован, он импортируется тогда. Если это уже было, выполнение продолжается.

+3

Иногда больше слов - это детали, но иногда больше слов - это просто больше слов. :) –

+0

Никогда не сравнивал это, но я, кажется, помню, что импорт не был таким быстрым. – max

+2

@ Гленн - слишком много кофе, не могу перестать печатать! – bgporter

15
class Handler(...): 
    ... 
    def render_with_jinja2(self, values, template_name): 
     import jinja2 
     env = jinja2.Environment(...) 
     ... 

Нет необходимости кэшировать импортированный модуль; Python делает это уже.

+1

Хм. Я думаю, я слышал, что включение модулей в локальную область не считается лучшей практикой - хотя я не уверен, почему. – max

+3

@mdorself Лучше практиковать то, что вы раскачивали. – aaronasterling

+1

@ aaronasterling заботиться о разработке? – max

8

Другие ответы покрыли фактические детали, но если вы являются заинтересованы в ленивой загрузки библиотеки, проверьте apipkg, который является частью пакета py (py.test известность).

+0

Это действительно здорово! – piokuc

+1

Он позволяет загружать только один раз в глобальном масштабе (а не в каждом из 27 мест, где происходит первый вызов '' jinja2''might_) и выполнять фактическую загрузку автоматически, когда (и только когда) первый доступ . Хорошая магия Питона. (Не пытайтесь это на C++.) –

+0

О, это потрясающе. Он даже не пытается загрузить, пока вы не получите доступ к некоторому * атрибуту * на ленивой загруженной вещи. Поэтому даже выполнение 'from mypkg import path' (из примера) ничего не импортирует, пока я не попытаюсь получить доступ к чему-либо на' path'. – jpmc26

Смежные вопросы