Что происходит, когда модуль импортируется дважды?

У меня есть сомнения, что я хотел бы проясниться.

Рассмотрим следующий модуль с именем ex_1.py:

print("Hello, I'm ex_1")
def greet(name):
 print("Hello, "+name+" nice to meet you! ")

Теперь рассмотрим другой файл с именем 1_client_ex_1.py, который будет импортировать модуль ex_1.py.

import ex_1.py

Теперь, когда я запускаю этот файл, я получаю вывод в виде:

Hello, I'm ex_1

Как и ожидалось.

Но когда я перехожу на 1_client_ex_1.py на:

import ex_1.py
import ex_1.py

и выполните его, он все еще печатает только Hello, I'm ex_1 один раз. Разве это не должно печатать это дважды?

Ответ 1

Ничего, если модуль уже импортирован, он не загружается снова.

Вы просто получите ссылку на модуль, который уже был импортирован (он будет получен от sys.modules).

Чтобы получить список уже импортированных модулей, вы можете найти sys.modules.keys() (обратите внимание, что urllib здесь импортирует много других модулей):

>>> import sys
>>> print len(sys.modules.keys())
44
>>> print sys.modules.keys()
['copy_reg', 'sre_compile', '_sre', 'encodings', 'site', '__builtin__', 'sysconfig', '__main__', 'encodings.encodings', 'abc', 'posixpath', '_weakrefset', 'errno', 'encodings.codecs', 'sre_constants', 're', '_abcoll', 'types', '_codecs', 'encodings.__builtin__', '_warnings', 'genericpath', 'stat', 'zipimport', '_sysconfigdata', 'warnings', 'UserDict', 'encodings.utf_8', 'sys', 'virtualenvwrapper', '_osx_support', 'codecs', 'readline', 'os.path', 'sitecustomize', 'signal', 'traceback', 'linecache', 'posix', 'encodings.aliases', 'exceptions', 'sre_parse', 'os', '_weakref']
>>> import urllib
>>> print len(sys.modules.keys())
70
>>> print sys.modules.keys()
['cStringIO', 'heapq', 'base64', 'copy_reg', 'sre_compile', '_collections', '_sre', 'functools', 'encodings', 'site', '__builtin__', 'sysconfig', 'thread', '_ssl', '__main__', 'operator', 'encodings.encodings', '_heapq', 'abc', 'posixpath', '_weakrefset', 'errno', '_socket', 'binascii', 'encodings.codecs', 'urllib', 'sre_constants', 're', '_abcoll', 'collections', 'types', '_codecs', 'encodings.__builtin__', '_struct', '_warnings', '_scproxy', 'genericpath', 'stat', 'zipimport', '_sysconfigdata', 'string', 'warnings', 'UserDict', 'struct', 'encodings.utf_8', 'textwrap', 'sys', 'ssl', 'virtualenvwrapper', '_osx_support', 'codecs', 'readline', 'os.path', 'strop', '_functools', 'sitecustomize', 'socket', 'keyword', 'signal', 'traceback', 'urlparse', 'linecache', 'itertools', 'posix', 'encodings.aliases', 'time', 'exceptions', 'sre_parse', 'os', '_weakref']
>>> import urllib #again!
>>> print len(sys.modules.keys()) #has not loaded any additional modules
70

Дайте ему вихрь:

import sys
>>> sys.modules["foo"] = "bar"  # Let pretend we imported a module named "foo", which is a string.
>>> print __import__("foo")
bar  # Not a module, that my string!

Как вы можете видеть, если модуль найден не sys.modules, вы просто получите новую ссылку на него. Что это.


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

Перезагрузка модулей за пределами интерактивного сеанса обычно не является очень хорошей практикой (хотя в ней есть свои варианты использования). В других ответах подробно рассказывается, как вы это сделаете.

Ответ 2

Скрипт Python загрузит модуль только один раз. Чтобы перезагрузить его, используйте:

reload()      # Python 2

и

imp.reload()  # Python 3

Ответ 3

Модуль загружается только при первом выполнении оператора import. См. Также reload() и этот вопрос. Вы можете изучить sys.modules, чтобы узнать, какие модули уже загружены.