这取决于您所拥有的“模块(预编译)”的确切含义。假设它恰好是
.pyc文件的内容,例如,
ciao.pyc通过以下方式构建:
$ cat>'ciao.py'def ciao(): return 'Ciao!' $ python -c'import ciao; print ciao.ciao()'Ciao!
IOW这样构建后
ciao.pyc,说您现在要做:
$ pythonPython 2.5.1 (r251:54863, Feb 6 2009, 19:02:12) [GCC 4.0.1 (Apple Inc. build 5465)] on darwinType "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<pre 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方式,也是获取常规位置的常用方法。
from的类型(除非它具有内置名称,否则您已经很方便了)来自标准库模块
types,因此,我建议这样做。
现在,最后:
>>> import ciao>>> ciao.ciao()'Ciao!'>>>
…您可以导入模块并使用其功能,类等。然后,其他
import(和
from)语句将找到该模块
sys.modules['ciao'],因此您无需重复此 *** 作序列(实际上,如果您只是想确保该模块可从其他位置导入,则在此
不需要 最后一条
import语句) -我添加它只是为了表明它有效;-)。
编辑
:如果您绝对必须以这种方式从中导入包和模块,而不是像我刚才所示的“纯模块”,那也是可行的,但是稍微复杂一点。由于这个答案已经很长了,我希望您可以通过为此使用简单的模块来简化您的生活,我将回避答案的那一部分;-)。
还要注意,在“多次从内存中加载同一模块”的情况下,这可能会或可能不会做您想要的(每次都会重新构建模块;您可能要检查sys.modules,如果模块已经存在,则跳过所有内容),尤其是当这种重复的“从内存中加载”是从多个线程中发生时(需要锁-
但更好的体系结构是只有一个专用线程来执行任务,而其他模块则通过队列与之通信)。
最后,没有讨论如何将此功能安装为透明的“导入钩子”,该钩子自动地参与了
import语句内部结构本身的机制-
这也是可行的,但并不完全是您要问的,所以在这里,我也希望您能通过简单的方法来简化生活,如答案所示。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)