Python: время жизни глобальных переменных модуля

У меня есть общий ресурс с высокой стоимостью инициализации, и поэтому я хочу получить к нему доступ по всей системе (в основном он используется для некоторых инструментов, поэтому должен быть легким). Итак, я создал модуль, управляющий настройкой и доступом к ней. Он выполняет ленивую инициализацию ресурса и сохраняет его в глобальной переменной модуля. Затем я использую функции этого модуля в системе для работы с ресурсом.
- Теперь мне интересно, придется ли (или как часто) повторно инициализировать ресурс?
- Я знаю, что объекты собираются мусором в CPython при (или, лучше, около) нулевом счетчике ссылок, но сохраняются ли они в модуле, считающемся ссылкой, даже если модуль в данный момент не выполняется?

Пример с кодом: здесь у нас есть модуль, где _connect () работает медленно. Я хочу использовать report_safely () в своей системе и в конечном итоге вызывать _connect () как можно реже.

__metrics = None


def _connect():
    global __metrics

    client = SomeSlowToSetUpClient()
    __metrics = SomeMetrics(client)
    client.connect()


def report_safely():
       if not __metrics:
           _connect()

       __metrics.execute_lightweight_code()

person Zakum    schedule 25.06.2013    source источник
comment
Один вопрос, который следует задать: уверены ли вы, что подключение этого устройства в основном все время после первого подключения - хорошая идея?   -  person voithos    schedule 25.06.2013
comment
Ну, эта штука только отправляет UDP-пакеты на сервер, поэтому я не вижу проблем с тем, чтобы оставаться на связи?   -  person Zakum    schedule 25.06.2013


Ответы (2)


Объекты, на которые больше нет ссылок, действительно собираются сборщиком мусора (они удаляются автоматически, когда их счетчик ссылок падает до 0).

Однако в глобальном модуле счетчик ссылок никогда не упадет до 0; однажды импортированный объект модуля (его пространство имен) живет в отображении sys.modules. Само пространство имен относится к вашему объекту.

Другими словами, ваш объект живет вечно, пока вы не удалите его из пространства имен модуля, не удалите само пространство имен модуля (del sys.modules['yourmodule']) или пока ваш скрипт python не завершится.

person Martijn Pieters    schedule 25.06.2013
comment
Звучит неплохо. Спасибо, Мартейн! Однако теперь мне интересно, что означает выход из сценария. Контекст - это приложение Django, и модули, импортирующие эту вещь, выполняются в рабочих потоках (сельдерей). Означает ли это, что модуль запускается при завершении каждого рабочего потока, или время жизни родительского элемента учитывается? Я имею в виду ... Я могу импортировать его где-нибудь в порождающем родительском потоке, но это звучит немного странно. - person Zakum; 25.06.2013
comment
@Zakum: рабочие Celery импортируют код только один раз, а затем запускают задачи в потоках. - person Martijn Pieters; 25.06.2013
comment
... что означает, что я в порядке, пока сельдерей работает. Большое спасибо! (На всякий случай оставлю эту вещь открытой еще на несколько часов / мнений, но похоже, что у вас есть веские претензии в отношении принятого ответа) - person Zakum; 25.06.2013

Если модуль, содержащий глобальный объект, находится в области видимости от начала вашего выполнения до конца, то глобальные переменные будут в. Хотя, возможно, будет чище использовать экземпляр класса.

person Steve Barnes    schedule 25.06.2013
comment
Моей первой идеей была и такая Java, как Singleton, но она казалась мне совершенно непонятной, поскольку в ней были только @classmethods и classvariables. Кроме того, тот же вопрос со сборкой мусора возникает с классом Singleton. - person Zakum; 25.06.2013