如何在Python 3.11中从字节序列加载模块而不保存到文件?

0 投票
0 回答
22 浏览
提问于 2025-04-12 00:16

我的加载器从服务器接收部分程序,格式是 .pyc 文件(这些文件并没有保存在客户端的文件系统中,而是以字节序列的形式存储在一个变量里)。

我需要从这个字节序列创建一个模块,而不想创建任何文件。

我找到了一种从字符串创建模块的方法:

spec = importlib.util.spec_from_loader("modulename", loader=None) # creating spec
module = importlib.util.module_from_spec(spec) # creating module
exec(source, module.__dict__) # executing module
#  so that we can import it in other program files
sys.modules[name] = module
globals()[name] = module

但是在我的情况下,这个方法不管用。

这个模块最开始是通过 py_compile.compile("sorcefile.py", "destfile.pyc") 创建的。对于一个类似的问题的回答(如何从内存加载编译过的Python模块?)建议使用 marshal.loads(bytes[8:]),确实,当我查看 py_compile.compile 函数的源代码时(https://svn.python.org/projects/python/trunk/Lib/py_compile.py),我发现它使用了 marshal.dump()。不过,据我了解,这段代码已经过时了,因为在我使用的Python版本(3.11)中查看这个函数的源代码时(https://github.com/python/cpython/blob/3.11/Lib/py_compile.py),我发现它不再使用marshal了。

这就解释了为什么在以下情况下会出现错误:

import marshal
import py_compile


py_compile.compile("source.py", "compiled.pyc")
with open("compiled.pyc", "rb") as f:
    module_bytes = f.read()

module = marshal.loads(module_bytes[8:])

输出:

Traceback (most recent call last):
  File "C:\test.py", line 9, in <module>
    module = marshal.loads(module_bytes[8:])
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: bad marshal data (unknown type code)

(在这个情况下,pyc文件只是为了模拟从服务器接收到的数据。)

那么,在Python 3.11中,是否有可能从字节序列创建模块,而不创建文件(就像用 "字符串" 方法那样)呢?

0 个回答

暂无回答

撰写回答