Предполагая, что Python 2, информация, которая, как мне кажется, вам нужна, находится в PEP 302 - New Import Hooks (PEP устарел для Python 3, что совершенно другое в этом отношении).
Поиск и импорт модулей из архивов ZIP осуществляется в zipimport, который «подключен» к механизму импорта, как описано PEP. Когда PEP 302 и импорт из ZIPs были добавлены в Python, модули imp
не были адаптированы, то есть imp
полностью не знает крючки PEP 302.
А «общий» find_module
функция, которая находит модули, как imp
делает и уважает PEP 302 крючков, будет примерно выглядеть следующим образом:
import imp
import sys
def find_module(fullname, path=None):
try:
# 1. Try imp.find_module(), which searches sys.path, but does
# not respect PEP 302 import hooks.
result = imp.find_module(fullname, path)
if result:
return result
except ImportError:
pass
if path is None:
path = sys.path
for item in path:
# 2. Scan path for import hooks. sys.path_importer_cache maps
# path items to optional "importer" objects, that implement
# find_module() etc. Note that path must be a subset of
# sys.path for this to work.
importer = sys.path_importer_cache.get(item)
if importer:
try:
result = importer.find_module(fullname, [item])
if result:
return result
except ImportError:
pass
raise ImportError("%s not found" % fullname)
if __name__ == "__main__":
# Provide a simple CLI for `find_module` above.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-p", "--path", action="append")
parser.add_argument("modname", nargs='+')
args = parser.parse_args()
for name in args.modname:
print find_module(name, args.path)
Примечание, однако, что результат от нахождения модуля в ZIP-архив выглядит совсем не так, как возвращается imp.find_module
: вы получите объект zipimport.zipimporter
для конкретного ZIP. Литт программа выше печатает следующее, когда его спросили, чтобы найти правильный модуль, встроенный в модуль и модуль из архивированного яйца:
$ python find_module.py grin os sys
<zipimporter object "<my venv>/lib/python2.7/site-packages/grin-1.2.1-py2.7.egg">
(<open file '<my venv>/lib/python2.7/os.py', mode 'U' at 0x10a0bbf60>, '<my venv>/lib/python2.7/os.py', ('.py', 'U', 1))
(None, 'sys', ('', '', 6))
Что делать, если ваш модуль находится глубоко внутри иерархии пакетов внутри архивного яйца? Какой путь вы хотите в этом случае? Там * * * файл, не эквивалентный тому, который вы запросили. – Kevin
@Kevin imp.find_module() только находит модули «toplevel». Например, вы можете найти «os», но вы не можете найти «путь» (например, «os.path»). Я просто хочу, чтобы find_module() работал так же, как и оператор import интерпретатора python. Переводчик загружает застрявшие яйца. – guettli
Механизм импорта в 2.x не полностью открыт. Под 3.x вы можете получить то, что хотите, с помощью 'importlib'; 'imp' устарел. К сожалению, это также означает, что все это существенно сложнее, чем когда-либо. – Kevin