Документация Python неофициальный перевод
Содержание страницы

31.3. imputil – Утилиты импортаimputil – Import utilities

Устарело с версии 2.6: Модуль imputil удалён в Python 3.

Этот модуль предоставляет очень удобный и полезный механизм для настраиваемых import хуков. По сравнению со старым модулем ihooks, imputil использует гораздо более простой и прямой подход к настраиваемым функциям import.

class imputil.ImportManager([fs_imp])

Управляет процессом импорта.

install([namespace])

Устанавливает этот ImportManager в указанное пространство имён.

uninstall()

Восстанавливает предыдущий механизм импорта.

add_suffix(suffix, importFunc)

Не документировано.

class imputil.Importer

Базовый класс для замены стандартных функций импорта.

import_top(name)

Импортирует модуль верхнего уровня.

get_code(parent, modname, fqname)

Находит и извлекает код для указанного модуля.

parent указывает родительский модуль для определения контекста импорта. Может быть None, что означает отсутствие конкретного контекста поиска.

modname указывает отдельный модуль (не составное имя) внутри родительского.

fqname указывает полное квалифицированное имя модуля. Это (потенциально) составное имя от “корня” пространства имён модулей до modname.

Если родитель отсутствует, то modname == fqname.

Этот метод должен возвращать None или кортеж из 3 элементов.

  • Если модуль не найден, следует вернуть None.

  • Первый элемент кортежа из 2 или 3 элементов должен быть целым числом 0 или 1, указывающим, является ли найденный модуль пакетом.

  • Второй элемент – это объект кода для модуля (он будет выполнен в пространстве имён нового модуля). Этот элемент также может быть полностью загруженным объектом модуля (например, загруженным из динамической библиотеки).

  • Третий элемент – это словарь пар имя/значение, которые будут вставлены в новый модуль до выполнения объекта кода. Это предусмотрено на случай, если код модуля ожидает определённые значения (например, где был найден модуль). Когда второй элемент является объектом модуля, эти имена/значения будут вставлены после загрузки/инициализации модуля.

class imputil.BuiltinImporter

Эмулирует механизм импорта для встроенных и замороженных модулей. Это подкласс класса Importer.

get_code(parent, modname, fqname)

Не документировано.

imputil.py_suffix_importer(filename, finfo, fqname)

Не документировано.

class imputil.DynLoadSuffixImporter([desc])

Не документировано.

import_file(filename, finfo, fqname)

Без документации.

31.3.1. ПримерыExamples

Это повторная реализация иерархического импорта модулей.

Этот код предназначен для чтения, а не для выполнения. Однако он работает – всё, что нужно сделать для его включения, – это «import knee».

(Название – это игра слов, отсылающая к более громоздкому предшественнику этого модуля – «ni».)

import sys, imp, __builtin__

# Замена для __import__()
def import_hook(name, globals=None, locals=None, fromlist=None):
    parent = determine_parent(globals)
    q, tail = find_head_package(parent, name)
    m = load_tail(q, tail)
    if not fromlist:
        return q
    if hasattr(m, "__path__"):
        ensure_fromlist(m, fromlist)
    return m

def determine_parent(globals):
    if not globals or  not globals.has_key("__name__"):
        return None
    pname = globals['__name__']
    if globals.has_key("__path__"):
        parent = sys.modules[pname]
        assert globals is parent.__dict__
        return parent
    if '.' in pname:
        i = pname.rfind('.')
        pname = pname[:i]
        parent = sys.modules[pname]
        assert parent.__name__ == pname
        return parent
    return None

def find_head_package(parent, name):
    if '.' in name:
        i = name.find('.')
        head = name[:i]
        tail = name[i+1:]
    else:
        head = name
        tail = ""
    if parent:
        qname = "%s.%s" % (parent.__name__, head)
    else:
        qname = head
    q = import_module(head, qname, parent)
    if q: return q, tail
    if parent:
        qname = head
        parent = None
        q = import_module(head, qname, parent)
        if q: return q, tail
    raise ImportError("No module named " + qname)

def load_tail(q, tail):
    m = q
    while tail:
        i = tail.find('.')
        if i < 0: i = len(tail)
        head, tail = tail[:i], tail[i+1:]
        mname = "%s.%s" % (m.__name__, head)
        m = import_module(head, mname, m)
        if not m:
            raise ImportError("No module named " + mname)
    return m

def ensure_fromlist(m, fromlist, recursive=0):
    for sub in fromlist:
        if sub == "*":
            if not recursive:
                try:
                    all = m.__all__
                except AttributeError:
                    pass
                else:
                    ensure_fromlist(m, all, 1)
            continue
        if sub != "*" and not hasattr(m, sub):
            subname = "%s.%s" % (m.__name__, sub)
            submod = import_module(sub, subname, m)
            if not submod:
                raise ImportError("No module named " + subname)

def import_module(partname, fqname, parent):
    try:
        return sys.modules[fqname]
    except KeyError:
        pass
    try:
        fp, pathname, stuff = imp.find_module(partname,
                                              parent and parent.__path__)
    except ImportError:
        return None
    try:
        m = imp.load_module(fqname, fp, pathname, stuff)
    finally:
        if fp: fp.close()
    if parent:
        setattr(parent, partname, m)
    return m


# Замена для reload()
def reload_hook(module):
    name = module.__name__
    if '.' not in name:
        return import_module(name, name, None)
    i = name.rfind('.')
    pname = name[:i]
    parent = sys.modules[pname]
    return import_module(name[i+1:], name, parent)


# Сохранить исходные хуки
original_import = __builtin__.__import__
original_reload = __builtin__.reload

# Теперь установить наши хуки
__builtin__.__import__ = import_hook
__builtin__.reload = reload_hook

Также см. модуль importers (находится в Demo/imputil/ в дистрибутиве исходного кода Python) для дополнительных примеров.