Какова форма функции импорта звезды в Python 3

Что эквивалентно import * в Python, используя функции (предположительно от importlib)?

Я знаю, что вы можете импортировать модуль с mod = __import__(...), который будет делегировать все текущие настройки. Вы также можете сделать что-то вроде

mod_spec = importlib.utl.spec_from_file_location(...)
mod = importlib.util.module_from_spec(mod_spec)
mod_spec.loader.exec_module(mod)

который позволяет вам делать сумасшедшие вещи, например, вводить вещи в модуль, вставляя их перед вызовом exec_module. (Предоставлено qaru.site/info/12695/... и qaru.site/info/386891/...)

Однако мой вопрос остается. Как import * работает в форме функции? Какая функция определяет, какие имена загружаются из модуля в зависимости от наличия/содержимого __all__?

Ответы

Ответ 1

Нет функции для from whatever import *. На самом деле, нет функции для import whatever, либо! Когда вы делаете

mod = __import__(...)

Функция __import__ отвечает только за часть задания. Он предоставляет вам объект модуля, но вы должны назначить этот объект модуля переменной отдельно. Нет функции, которая будет импортировать модуль и назначить его переменной, как это делает import whatever.


В from whatever import * есть две части:

  • подготовить объект модуля для whatever
  • назначить переменные

Часть "подготовить объект модуля" почти идентична в import whatever, и ее можно обрабатывать с помощью той же функции __import__. Там незначительная разница в том, что import * будет загружать любые еще не загруженные подмодули в пакет __all__; __import__ будет обрабатывать это для вас, если вы предоставите fromlist=['*']:

module = __import__('whatever', fromlist=['*'])

Часть о назначении имен - это то место, где происходят большие различия, и, опять же, вы должны справиться с этим сами. Это довольно просто:

if hasattr(module, '__all__'):
    all_names = module.__all__
else:
    all_names = [name for name in dir(module) if not name.startswith('_')]

globals().update({name: getattr(module, name) for name in all_names})