Зачем мне явно импортировать модули, когда они уже импортированы?

1

Всякий раз, когда я запускаю команду на 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 для его использования. Почему это происходит?

  • 4
    import каждого пространства имен . Импорт чего-либо в пространство имен одного модуля сохраняет его в кэше, но не делает его доступным для других модулей без явного запроса - если бы это было не так, вы бы никогда не узнали, какие имена были и не были в вашем пространстве имен, потому что они могли быть случайно импортированы другим кодом в системе!
Теги:
sys

1 ответ

1
Лучший ответ

Краткая (и неточная) версия: import foo выполняет две отдельные вещи:

  • он ищет и загружает с диска модуль с именем "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
  • 0
    importlib.__import__ - оксюморон. Используйте importlib.import_module .
  • 0
    @wim: я не думаю, что это слово означает то, что, как вы думаете, оно означает… в любом случае, да, __import__() не рекомендуется в пользу import_module() , но первое - это то, что вызывается оператором import .
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню