Почему функция, кажется, импортирует один раз? - PullRequest
2 голосов
/ 17 июня 2019

У меня есть три файла file_a.py, file_b.py и func.py:

В func.py, у меня есть:

import datetime

def a_simple_function():
    print("hello from simple function")
    return datetime.datetime.now()

global_variable = a_simple_function()

В file_b.py, у меня есть:

from func import global_variable  # second time import

def func_in_b():
    print("print from file b:", global_variable)

В file_a.py у меня есть:

from func import global_variable  # first time import 
from file_b import func_in_b

print("print from file a:", global_variable)
func_in_b()

При запуске с file_a я вижу следующий вывод:

hello from simple function
print from file a: 2019-06-17 14:14:42.293202
print from file b: 2019-06-17 14:14:42.293202

Почему hello from simple function появляется один раз вместо двух? Я думаю, что я импортировал его дважды в разных файлах.

В основном я пытаюсь установить global_variable, используемый в file_a.py и file_b.py, global_variable генерируется функцией в файле func.py.

Ответы [ 3 ]

4 голосов
/ 17 июня 2019

Вот как работает импорт, как описано в документации: https://docs.python.org/3/tutorial/modules.html#more-on-modules. В частности:

Модуль может содержать как исполняемые операторы, так и определения функций.Эти операторы предназначены для инициализации модуля.Они выполняются только в первый раз, когда имя модуля встречается в операторе импорта.

По существу, оператор import сначала проверяет, содержит ли sys.modules ваш модуль.Если это так, возвращается существующая ссылка, как во втором случае.Если нет, то создается пустой объект модуля, добавляется в sys.modules и только затем заполняется путем запуска файла .py.Причина для этого заключается в том, чтобы избежать циклов из циклического импорта: модуль не будет перезагружен в таком цикле, даже если его объект все еще пуст.

Ссылки на global_variable во всех трехфайлы указывают на один и тот же объект.Вы можете проверить file_a, добавив следующее к существующему коду:

import func
import file_b
import sys

print(func.global_variable is file_b.global_variable is global_variable is sys.modules['func'].global_variable)

Следует помнить, что при запуске модуля в качестве сценария он будет помещен в sys.modules под именем __main__.Любой код, который пытается импортировать его под своим обычным именем, загружает другой объект модуля, что иногда приводит к неожиданным последствиям.

3 голосов
/ 17 июня 2019

Импорт кэшей Python в sys.modules.Поэтому, даже если вы импортируете один и тот же модуль несколько раз, он будет использовать кэшированные версии вместо многократного импорта.

Подробнее о кэше модуля читайте для получения дополнительной информации.

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

Это потому, что когда вы импортировали global_variable в файл file_a.py, функция a_simple_function() определяется в памяти и сохраняется в кеше Python. В следующий раз, когда вы импортируете переменную global_variable в файл file_b.py, функция a_simple_function() уже находится в кэше, поэтому она не будет определена снова, вместо этого вы получите значение global_variable оттуда.

...