当前位置: 首页 > 面试题库 >

如何从内存加载已编译的python模块?

秦皓君
2023-03-14
问题内容

我需要从一个zip文件(由py2exe压缩生成)中读取所有模块(预编译)到内​​存中,然后将它们全部加载。我知道这可以通过直接从zip文件加载来完成,但是我需要从内存中加载它们。有任何想法吗?(我在Windows上使用python
2.5.2)TIA Steve


问题答案:

这取决于您所拥有的“模块(预编译)”的确切含义。假设它恰好是.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通常使用的顺序,因此最好模仿它(没有特定的缺点)。

您可以通过几种方式“创建新的模块对象”(例如,从标准库模块中的函数,如newimp),但是“调用类型以获取实例”是当今的常规Python方式,也是获取常规位置的常用方法。
from的类型(除非它具有内置名称,否则您已经很方便了)来自标准库模块types,因此,我建议这样做。

现在,最后:

>>> import ciao
>>> ciao.ciao()
'Ciao!'
>>>

…您可以导入模块并使用其功能,类等。然后,其他import(和from)语句将找到该模块sys.modules['ciao'],因此您无需重复此操作序列(实际上,如果您只是想确保该模块可从其他位置导入,则在此
不需要 最后一条import语句) -我添加它只是为了表明它有效;-)。

编辑
:如果您绝对必须以这种方式从中导入包和模块,而不是像我刚才所示的“纯模块”,那也是可行的,但是稍微复杂一点。由于这个答案已经很长了,我希望您可以通过为此使用简单的模块来简化您的生活,我将回避答案的那一部分;-)。

还要注意,在“多次从内存中加载同一模块”的情况下,这可能会或可能不会做您想要的(每次都会重新构建模块;您可能要检查sys.modules,如果模块已经存在,则跳过所有内容),尤其是当这种重复的“从内存中加载”是从多个线程中发生时(需要锁-
但更好的体系结构是只有一个专用线程来执行任务,而其他模块则通过队列与之通信)。

最后,没有讨论如何将此功能安装为透明的“导入钩子”,该钩子自动地参与了import语句内部结构本身的机制-
这也是可行的,但并不完全是您要问的,所以在这里,我也希望您能通过简单的方法来简化生活,如答案所示。



 类似资料:
  • 我运行了一个简单的程序,它允许我将HTTP请求映射到一个函数——这很棒,所以我决定,与其简单地返回一个随机字符串,我还可以轻松地返回一个字符串格式的超文本标记语言页面,就像能够动态地提供静态超文本标记语言页面一样。 问题是我无法加载网页资源。 我的项目具有以下结构: 正如我所说,如果我只是想返回一个字符串,我的程序工作正常,它正在尝试加载我似乎无法管理的home.html文件,特别是我的问题是如何

  • 我有一个python程序,其中我需要加载和反序列化一个1GB的pickle文件。它需要一个良好的20秒,我想有一个机制,使腌菜的内容是随时可用的使用。我看过shared_memory,但是所有使用它的例子似乎都涉及到numpy,而我的项目没有使用numpy。使用或其他方式实现此目标的最简单、最干净的方法是什么? 这就是我现在(每次运行时)加载数据的方式: 我一直在使用,但对于一个包含许多文件的大型

  • 问题内容: 如果我将文件的内容作为字符串存储在内存中而不将其写出到磁盘,该如何请求文件?这是一个例子: 问题答案: 在module.js中查看_compile,_extensions和_load

  • 问题内容: 我有一个同时具有两个外部内核模块和一个用户空间守护程序的应用程序。我想在启动时从用C编写的守护程序代码中加载模块,然后在干净退出时将其卸载。我可以用比使用相应的方式更干净的方式加载它们吗? 问题答案: 最小的可运行示例 使用此简单的参数打印机模块,在QEMU + Buildroot VM和Ubuntu 16.04主机上进行了测试。 我们使用/ 和 Linux系统调用。 Linux内核为

  • 问题内容: 我如何在运行时从字符串生成字节码(Byte []),而无需使用“ javac”进程或类似的东西?有没有像这样调用编译器的简单方法? 以后添加: 我选择接受最适合 我的 情况的解决方案。我的应用程序是一个尚处于设计草图阶段的业余项目,现在是考虑插入新技术的合适时机。另外,由于应该帮助我解决BL的人是JavaScript开发人员,因此在这种情况下,使用JavaScript解释器而不是存根编

  • 问题内容: 我有一台运行时间较长的Python服务器,并且希望能够在不重新启动服务器的情况下升级服务。最好的方法是什么? 问题答案: 你可以使用reload内置函数重新加载已导入的模块: 在Python 3中,已移至imp模块。在3.4中,不推荐使用importlib,而在中添加了。当定位到3或更高版本时,在调用reload或导入时参考相应的模块。 我认为这就是你想要的。诸如Django开发服务器