简体   繁体   English

如何导入.pyc编译的python文件并使用它

[英]How can I import a .pyc compiled python file and use it

Im trying to figure out how to include a .pyc file in a python script. 我试图弄清楚如何在python脚本中包含.pyc文件。

For example my script is called: 例如,我的脚本被调用:

myscript.py

and the script I would like to include is called: 我想要包含的脚本称为:

included_script.pyc

So, do I just use: 那么,我只是使用:

import included_script

And will that automatically execute the included_script.pyc ? 那会自动执行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.pycmyscript.py运行?

Do I need to pass the variables used in included_script.pyc also? 我是否还需要传递included_script.pyc使用的变量? 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. 当然,你可以用坚韧不拔的方式手动完成


Setup: 设定:

For demonstration purposes, I'll first generate a .pyc file. 出于演示目的,我将首先生成.pyc文件。 In order to do that, we first need a .py file for it. 为此,我们首先需要一个.py文件。 Our sample test.py file will look like: 我们的示例test.py文件如下所示:

def foo():
    print("In foo")

if __name__ == "__main__":
    print("Hello World")

Super simple. 超级简单。 Generating the .pyc file can done with the py_compile module found in the standard library. 生成.pyc文件可以使用标准库中的py_compile模块完成。 We simply pass in the name of the .py file and the name for our .pyc file in the following way: 我们只需通过以下方式传入.py文件的名称和.pyc文件的名称:

 py_compile.compile('test.py', 'mypyc.pyc')

This will place mypyc.pyc in our current working directory. 这会将mypyc.pyc放在我们当前的工作目录中。


Getting the code from .pyc files: .pyc文件获取代码:

Now, .pyc files contain bytes that are structured in the following way: 现在, .pyc文件包含以下列方式构造的字节:

  • First 4 bytes signalling a 'magic number' 前4个字节表示“幻数”
  • Next 4 bytes holding a modification timestamp 接下来的4个字节包含修改时间戳
  • Rest of the contents are a marshalled code object. 其余内容是编组的 code对象。

What we're after is that marshalled code object, so we need to import marshal to un-marshall it and execute it. 我们所追求的是编组的code对象,因此我们需要import marshal来解组并执行它。 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): 另外,我们真的不关心/需要8个第一个字节,并且不允许用它们解组.pyc文件,因此我们将忽略它们( seek它们):

import marshal

s = open('mypyc.pyc', 'rb')
s.seek(8)  # go past first eight bytes
code_obj = marshal.load(s)

So, now we have our fancy code object for test.py which is valid and ready to be executed as we wish. 所以,现在我们为test.py提供了我们的花式code对象,该对象是有效的并且可以随意执行。 We have two options here : 我们有两个选择

  1. Execute it in the current global namespace. 在当前global命名空间中执行它。 This will bind all definitions inside our .pyc file in the current namespace and will act as a sort of: from file import * statement. 这将绑定当前命名空间中.pyc文件中的所有定义,并将作为一种: from file import *语句。

  2. Create a new module object and execute the code inside the module. 创建一个新的模块对象并执行模块内的代码。 This will be like the import file statement. 这将像import file语句。


Emulating from file import * like behaviour: from file import *模拟行为:

Performing this is pretty simple, just do: 执行此操作非常简单,只需:

exec(code_obj)

This will execute the code contained inside code_obj in the current namespace and bind everything there. 这将执行当前命名空间中code_obj中包含的代码并绑定其中的所有内容。 After the call we can call foo like any other funtion: 通话结束后,我们可以像任何其他功能一样调用foo

foo()
# prints: In foo!

Note : exec() is a built-in. 注意exec()是内置的。


Emulating import file like behaviour: 像行为一样模拟import file

This includes another requirement, the types module. 这包括另一个要求, types模块。 This contains the type for ModuleType which we can use to create a new module object. 它包含ModuleType的类型,我们可以使用它来创建新的模块对象。 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)>

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__ ):

exec(code_obj, m.__dict__)

Now, our module m has everything defined in code_obj , you can verify this by running: 现在,我们的模块m具有code_obj定义的code_obj ,您可以通过运行以下命令来验证:

m.foo() 
# prints: In foo

These are the ways you can 'include' a .pyc file in your module. 这些是您可以在模块中“包含” .pyc文件的方法。 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. 我真的没有看到这方面的实用性,但是嘿,我不是来判断的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM