Всякий раз, когда я запускаю команду на Ubuntu Linux:
python3 -v
Я получаю подробный вывод, который говорит мне:
import _frozen_importlib # frozen
import _imp # builtin
import sys # builtin
import '_warnings' # <class '_frozen_importlib.BuiltinImporter'>
import '_thread' # <class '_frozen_importlib.BuiltinImporter'>
import '_weakref' # <class '_frozen_importlib.BuiltinImporter'>
import '_frozen_importlib_external' # <class '_frozen_importlib.FrozenImporter'>
import '_io' # <class '_frozen_importlib.BuiltinImporter'>
И многое другое.
Тем не менее, я вижу, что import sys был выполнен, но мне все еще нужно вручную импортировать sys для его использования. Почему это происходит?
Краткая (и неточная) версия: import foo
выполняет две отдельные вещи:
foo
в текущем пространстве имен Вы должны "вручную импортировать" sys
по той же причине, что это не работает:
>>> def r():
... import random
... print(random.randint(0, 100))
...
>>> r()
26
>>> random.randint(10, 20)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'random' is not defined
Способ продемонстрировать, что импорт не является чем-то волшебным:
$ cat foo.py
print('foo has been imported')
def fn():
print('fn has been called')
$ python
>>> import importlib
>>> bar = importlib.__import__('foo')
foo has been imported
>>> bar.fn()
fn has been called
Имя модуля работает как любое другое имя в Python:
importlib.__import__()
создает значение (в этом случае модуль), а =
присваивает ему имя.
При обычном импорте import foo
создает значение (тот же модуль) и присваивает его данному имени (которое просто совпадает с именем модуля).
Вы можете проверить, что модуль загружается только один раз:
$ python
>>> import foo
foo has been imported
>>> import foo
>>>
и вы можете продемонстрировать, что модуль является еще одним значением:
>>> import foo
foo has been imported
>>> foo.fn()
fn has been called
>>> bar = foo
>>> bar.fn()
fn has been called
importlib.__import__
- оксюморон. Используйте importlib.import_module
.
__import__()
не рекомендуется в пользу import_module()
, но первое - это то, что вызывается оператором import
.
import
каждого пространства имен . Импорт чего-либо в пространство имен одного модуля сохраняет его в кэше, но не делает его доступным для других модулей без явного запроса - если бы это было не так, вы бы никогда не узнали, какие имена были и не были в вашем пространстве имен, потому что они могли быть случайно импортированы другим кодом в системе!