Это зависит от того, что именно у вас есть как «модуль (предварительно скомпилированный)». Давайте предположим, что это именно содержимое файла .pyc
, например, ciao.pyc
, созданного с помощью:
$ cat>'ciao.py'
def ciao(): return 'Ciao!'
$ python -c'import ciao; print ciao.ciao()'
Ciao!
IOW, построив таким образом ciao.pyc
, скажите, что вы сейчас делаете:
$ python
Python 2.5.1 (r251:54863, Feb 6 2009, 19:02:12)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> b = open('ciao.pyc', 'rb').read()
>>> len(b)
200
и ваша цель - перейти от этой строки байтов b
к импортируемому модулю ciao
. Вот как это сделать:
>>> import marshal
>>> c = marshal.loads(b[8:])
>>> c
<code object <module> at 0x65188, file "ciao.py", line 1>
так вы получаете объект кода из двоичного содержимого .pyc
. Редактировать : если вам любопытно, первые 8 байтов - это «магическое число» и временная метка - здесь не требуется (если только вы не хотите проверять их работоспособность и вызывать исключения, если это оправдано, но это кажется вне рамок вопроса; marshal.loads
все равно будет вызываться, если обнаружит поврежденную строку).
Тогда:
>>> import types
>>> m = types.ModuleType('ciao')
>>> import sys
>>> sys.modules['ciao'] = m
>>> exec c in m.__dict__
Т.е.: создать новый объект модуля, установить его в sys.modules
, заполнить его, выполнив объект кода в его __dict__
. Редактировать : порядок, в котором вы делаете вставку sys.modules
и exec
, имеет значение тогда и только тогда, когда у вас может быть циклический импорт - но это порядок, который обычно использует собственный Python import
, поэтому лучше подражать этому (у которого нет никаких определенных недостатков).
Вы можете «создать новый объект модуля» несколькими способами (например, из функций в стандартных модулях библиотеки, таких как new
и imp
), но «вызов типа для получения экземпляра» является обычным способом Python В наши дни обычное место для получения типа (если у него нет встроенного имени или у вас его нет под рукой) - стандартный библиотечный модуль types
, поэтому я рекомендую.
Теперь наконец-то:
>>> import ciao
>>> ciao.ciao()
'Ciao!'
>>>
... вы можете импортировать модуль и использовать его функции, классы и так далее. Другие операторы import
(и from
) затем найдут модуль как sys.modules['ciao']
, поэтому вам не нужно будет повторять эту последовательность операций (на самом деле вам не нужно это последнее * 1046) * здесь заявление, если все, что вам нужно, это убедиться, что модуль доступен для импорта из других мест - я добавляю его только для того, чтобы показать, что он работает; -).
Редактировать : Если вам абсолютно необходимо импортировать таким образом пакеты и модули из них, а не "простые модули", как я только что показал, это тоже выполнимо, но немного сложнее. Поскольку этот ответ уже довольно длинный, и я надеюсь, что вы можете упростить свою жизнь, придерживаясь простых модулей для этой цели, я собираюсь уклониться от этой части ответа; -).
Также обратите внимание, что это может или не может делать то, что вы хотите в случае «загрузки одного и того же модуля из памяти несколько раз» (это перестраивает модуль каждый раз; вы можете захотеть проверить sys.modules и просто пропустить все, если модуль уже существует) и, в частности, когда такая повторяющаяся «загрузка из памяти» происходит из нескольких потоков (требующих блокировок - но, лучшая архитектура состоит в том, чтобы иметь один выделенный поток, предназначенный для выполнения задачи, с другими модулями, связывающимися с ним через Очередь).
Наконец, не обсуждается вопрос о том, как установить эту функциональность в качестве прозрачной «ловушки импорта», которая автоматически включается в механизмы самих внутренних элементов оператора import
- это тоже возможно, но не совсем то, что вы Я спрашиваю о том, что и здесь, я надеюсь, вы также можете упростить свою жизнь, выполняя простые вещи, как показано в этом ответе.