如何导入 .pyc 编译的 python 文件并使用它
问题描述
我试图弄清楚如何在 python 脚本中包含 .pyc
文件.
Im trying to figure out how to include a .pyc
file in a python script.
例如我的脚本被称为:
myscript.py
我想包含的脚本被称为:
and the script I would like to include is called:
included_script.pyc
那么,我只是使用:
import included_script
那会自动执行 included_script.pyc
吗?或者我还需要做些什么来让我的 included_script.pyc
在 myscript.py
中运行?
And will that automatically execute the included_script.pyc
? Or is there something further I need to do, to get my included_script.pyc
to run inside the myscript.py
?
我还需要传递 included_script.pyc
中使用的变量吗?如果可以,如何实现?
Do I need to pass the variables used in included_script.pyc
also? If so, how might this be achieved?
解决方案
很遗憾,不,这不能自动完成.当然,您也可以以一种非常丑陋的方式手动完成.
Unfortunately, no, this cannot be done automatically. You can, of course, do it manually in a gritty ugly way.
出于演示目的,我将首先生成一个 .pyc
文件.为此,我们首先需要一个 .py
文件.我们的示例 test.py
文件如下所示:
For demonstration purposes, I'll first generate a .pyc
file. In order to do that, we first need a .py
file for it. Our sample test.py
file will look like:
def foo():
print("In foo")
if __name__ == "__main__":
print("Hello World")
超级简单.生成 .pyc
文件可以使用 py_compile
模块在标准库中找到.我们只需通过以下方式传入 .py
文件的名称和 .pyc
文件的名称:
Super simple. Generating the .pyc
file can done with the py_compile
module found in the standard library. We simply pass in the name of the .py
file and the name for our .pyc
file in the following way:
py_compile.compile('test.py', 'mypyc.pyc')
这会将 mypyc.pyc
放在我们当前的工作目录中.
This will place mypyc.pyc
in our current working directory.
现在,.pyc
文件包含以下结构的字节:
Now, .pyc
files contain bytes that are structured in the following way:
- 前 4 个字节表示幻数"
- 接下来的 4 个字节包含修改时间戳
- 其余内容是编组的
code
对象.
我们需要的是编组的 code
对象,所以我们需要 import marshal
解组并执行它.此外,我们真的不关心/不需要前 8 个字节,并且不允许使用它们解组 .pyc
文件,因此我们将忽略它们(seek
过去):
What we're after is that marshalled code
object, so we need to import marshal
to un-marshall it and execute it. Additionally, we really don't care/need the 8 first bytes, and un-marshalling the .pyc
file with them is disallowed, so we'll ignore them (seek
past them):
import marshal
s = open('mypyc.pyc', 'rb')
s.seek(8) # go past first eight bytes
code_obj = marshal.load(s)
所以,现在我们有了用于 test.py
的花哨的 code
对象,它是有效的,可以按照我们的意愿执行.这里有两种选择:
So, now we have our fancy code
object for test.py
which is valid and ready to be executed as we wish. We have two options here:
在当前的
global
命名空间中执行它.这将绑定当前命名空间中我们的.pyc
文件中的所有定义,并将充当一种:from file import *
语句.
Execute it in the current
global
namespace. This will bind all definitions inside our.pyc
file in the current namespace and will act as a sort of:from file import *
statement.
创建一个新的模块对象并执行模块内的代码.这类似于 import file
语句.
Create a new module object and execute the code inside the module. This will be like the import file
statement.
<小时>
模拟 from file import *
类似的行为:
执行此操作非常简单,只需执行以下操作:
Emulating from file import *
like behaviour:
Performing this is pretty simple, just do:
exec(code_obj)
这将在当前命名空间中执行 code_obj
中包含的代码并绑定那里的所有内容.调用之后,我们可以像调用任何其他函数一样调用 foo
:
This will execute the code contained inside code_obj
in the current namespace and bind everything there. After the call we can call foo
like any other funtion:
foo()
# prints: In foo!
注意:exec()
是内置的.
这包括另一个要求,types
模块.这包含 ModuleType
<的类型/a> 我们可以使用它来创建一个新的模块对象.它有两个参数,模块的名称(强制)和它的文档(可选):
This includes another requirement, the types
module. This contains the type for ModuleType
which we can use to create a new module object. It takes two arguments, the name for the module (mandatory) and the documentation for it (optional):
m = types.ModuleType("Fancy Name", "Fancy Documentation")
print(m)
<module 'Fancy Name' (built-in)>
现在我们有了模块对象,我们可以再次使用 exec
来执行模块命名空间内的 code_obj
中包含的代码(即 m.__dict__
):
Now that we have our module object, we can again use exec
to execute the code contained in code_obj
inside the module namespace (namely, m.__dict__
):
exec(code_obj, m.__dict__)
现在,我们的模块 m
已经在 code_obj
中定义了所有内容,您可以通过运行来验证这一点:
Now, our module m
has everything defined in code_obj
, you can verify this by running:
m.foo()
# prints: In foo
<小时>
这些是您可以在模块中包含".pyc
文件的方法.至少,我能想到的方法.我真的看不出这有什么实用性,但是嘿,我不是来评判的.
These are the ways you can 'include' a .pyc
file in your module. At least, the ways I can think of. I don't really see the practicality in this but hey, I'm not here to judge.
相关文章