当前位置: 首页 > 工具软件 > pyC11 > 使用案例 >

python 编译pyc以及pyc包导入使用

齐俊贤
2023-12-01

python 编译pyc以及pyc包导入使用

     目前做一个项目,为了保护源码,如何发布解析之后的二进制文件.pyc,给工程使用,这里做一个较为简单和详细的解释。

一、基础概念

       包:一个文件夹,用来存放模块和子包。包里一般会有一个__init__.py 的文件(也可以没有),包里一般也会有一个__pycache__文件夹,存放 .py 文件经解释器解释后的中间字节码(二进制文件)。

      模块: 可以作为模块的文件有 .py ,.pyc, .pyo, .pyd, .so, .dll文件。这里主要介绍 .pyc 文件。

 二、具体生成 

     python 解释器在解释.py 文件时,会优先查看是否有对应的最新的.pyc 文件,有的话会直接加载.pyc 文件。在加载之前,会检查.pyc 文件是不是最新的。

     pyc是一种二进制文件,是由py文件经过编译后,生成的文件,是一种byte code,py文件变成pyc文件后,加载的速度有所提高,而且pyc是一种跨平台的字节码,是由python的虚拟机来执行的,pyc的内容,是跟python的版本相关的,不同版本编译后的pyc文件是不同的,2.5编译的pyc文件,2.4版本的python是无法执行的。

     为什么需要pyc

      因为py文件是可以直接看到源码的,如果你是开发商业软件的话,不可能把源码也泄漏出去吧?所以就需要编译为pyc后,再发布出去。当然,pyc文件也是可以反编译的,不同版本编译后的pyc文件是不同的,根据python源码中提供的opcode,可以根据pyc文件反编译出py文件源码,这一步不重要。

     代码编译生成

     对于单个文件,使用方法非常简单,如下所示,***.py是需要编译的python源文件:

 import py_compile
 py_compile.compile('****.py')

    对于多个文件一般来说,我们的工程都是在一个目录下的,一般不会说仅仅编译一个py文件而已,而是需要把整个文件夹下的py文件都编译为pyc文件,python又为了我们提供了另一个模块:compileall 。使用方法如下:

import compileall
compileall.compile_dir(r'/Users/***/PythonFiles/')

   Python Shell 命令生成

   直接通过命令来运行,可以看到下面的命令中并没有用到compile()函数, 这是因为py_compile模块的main()函数中调用了compile().

    python3 -m py_compile ****.py

    python3 --m py_compile ****.py

    -O 优化成字节码

   -m 表示把后面的模块当成脚本运行

   -OO 表示优化的同时删除文档字符串

 如果你想看compile(), compile_dir(), compile_path()具体每个参数是干吗用的,可以使用print py_compile.compile().__doc__来查看,或者直接打开py_compile.py,compileall.py文件来看。

三、具体使用

        直接使用python编译源码时,会生成对应的(.pyc)文件,这些文件会被存放在__pycache__文件夹下,我们可以将里边的文件copy出来,这时候可以删除对应的.py文件,同时需要将***.pyc文件的名字进行修改。

  例如: python 的.py文件叫 main.py, 生成的.pyc文件叫main.cpython-36.pyc,在我们使用该模块的时候,需要将main.cpython-36.pyc修改为main.pyc, 这里的“cpython-36”表示的是我在python 3.6 的环境下编译的。

注意 :如果你直接从一个环境中copy到另一个环境中会出现一些bug,我遇到一个,在这里分享一下,如果有其它有趣的bug,记得留言分享。

   ImportError: bad magic number in 'main':b '3\r*****'

   主要原因是编译的python版本与目前运行的python版本不同导致的。编译成.pyc文件之后,尽量保证编译环境与运行环境一致。

 类似资料: