Глобальные модули Python с множественным импортом - PullRequest
0 голосов
/ 19 июня 2019

Какой код запускается, а какой нет, когда модуль импортируется в python?

Какой код запускается, а какой нет, когда модуль импортируется во второй раз в python?

module1.py

GLOBAL_VAR = 'orig'

print('module1: GLOBAL_VAR = {}'.format(GLOBAL_VAR))

def init():
    global GLOBAL_VAR
    print('module1:init(1): GLOBAL_VAR = {}'.format(GLOBAL_VAR))
    GLOBAL_VAR = 'changed'
    print('module1:init(2): GLOBAL_VAR = {}'.format(GLOBAL_VAR))

module2.py

print('module2: importing module1')
import module1

print('module2(1): module1.GLOBAL_VAR = {}'.format(module1.GLOBAL_VAR))

module1.init()

print('module2(2): module1.GLOBAL_VAR = {}'.format(module1.GLOBAL_VAR))

module3.py

print('module3: importing module1')
import module1

print('module3(1): module1.GLOBAL_VAR = {}'.format(module1.GLOBAL_VAR))

main.py

import module2
import module3

выход

python3 main.py

module2: importing module1
module1: GLOBAL_VAR = orig
module2(1): module1.GLOBAL_VAR = orig
module1:init(1): GLOBAL_VAR = orig
module1:init(2): GLOBAL_VAR = changed
module2(2): module1.GLOBAL_VAR = changed
module3: importing module1
module3(1): module1.GLOBAL_VAR = changed

По сути, «автономный» - не в функции, не в классе - код запускается только один раз. Я хотел бы узнать больше об этом, как это работает, каковы ограничения, особенно, когда это не так?

Моя догадка заключается в том, что импортированные модули, даже если они импортированы из разных модулей, регистрируются на уровне "для каждого интерпретатора", и интерпретатор знает, уже выполнен ли код в модуле, и после этого он поддерживает текущее состояние любого модуля в объекте, и каждый импортер получает этот поддерживаемый объект.

Но что может это испортить? Что если я использую потоки, а второй модуль импортирует X-модуль, но у X-модуля очень длинный код для выполнения, и он не завершился к тому времени, когда второй импорт получил временной интервал? Что будет со всей этой системой, если я буду использовать многопроцессорность?

К сожалению, я не нашел хорошего объяснения.

Итак, я уже проверял, как это работает в базовой настройке, я уже так много знаю, мой вопрос: почему он работает так, каков основной механизм?

1 Ответ

0 голосов
/ 19 июня 2019

Вы правы, утверждая, что весь код верхнего уровня выполняется при первом импорте.Это включает определения функций (но не их тело), ​​которые связывают имя функции с объектом функции.

Как только модуль импортируется, он сохраняется в sys.modules.Это dict сопоставление имен модулей с объектом модуля.Таким образом, после import module_a вы можете обозначить его как sys.modules['module_a'].Вы даже можете удалить его из dict (см. Что на самом деле делает "del sys.modules [module]"? за последствия этого).Если вы не удалите модуль из sys.modules, все последующие импорты просто получат объект оттуда.Подробное описание системы импорта можно найти здесь: https://docs.python.org/3/reference/import.html

Что касается многопоточности, это обычно не проблема из-за глобальной блокировки интерпретатора (GIL): https://docs.python.org/3/c-api/init.html?highlight=gil#thread-state-and-the-global-interpreter-lock

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...