Python和Java的解释方式对比

Java:源代码 -> 编译成class -> Jvm解释运行

Python:源代码 -> Python解释器解释运行

我经常和身边的Java开发者开玩笑说:“Java真变态,别的语言都是要么直接编译要么直接解释,Java太另类了又编译又解释的......”

直接解释和编译后解释其实最大的区别就是源代码的安全性。

如果是直接解释源代码,那么源代码没有安全性可言,也就是任何一个人都可以打开源代码一看究竟,任何人都可以随意修改源代码。

事实上,Python和Java的解释方式是相同的,只是我们表面上看Python是直接解释源代码,而实际上python解释器只会加载字节码。细心的小伙伴肯定发现了这一点,当我们import某个模块时,总是会在模块所在的目录创建一个pycache目录,里面存放着被加载模块的字节码文件。

编译源代码有以下作用:

1、源代码保护(算法保护)/ 防止用户篡改源代码
2、解释器加载代码速度加快

pyc和pyo的生成方法

pyc的作用是用来跨平台使用的,和Java中的Class文件类似。pyc文件是一种字节码文件,可以加快Python解释器的加载速度,当然也可以用来做简单的防源码泄露保护。

pyo则是优化过后的字节码文件,不过pyo更像编译型语言里的中间文件。

我们可以通过Python提供的py_compile模块来进行源代码的编译。

py_compile模块只提供3个方法,分别是有关编译异常PyCompileError、有关编译compile、有关程序入口main

我们要用到的是compile方法,compile原形如下:

compile方法原形

compile(file, cfile=None, dfile=None, doraise=False, optimize=-1)

有5个参数:

file:必选参数,要编译的源文件

cfile:编译后的文件,默认在源文件目录下的pycache/源文件名.解释器类型-python版本.字节码类型

例如:pycache/abc.cpython-34.pyo

dfile:错误消息文件,默认和cfile一样

doraise:是否开启异常处理,默认False

编译案例:
准备源文件a.py和b.py,内容相同,就是一句print("python")代码

编写编译脚本:

import py_compile

py_compile.compile(file = "a.py",cfile = "a.pyc",optimize=-1)

py_compile.compile(file = "b.py",cfile = "b.pyo",optimize=1)

图片说明
图片说明

可见,字节码文件成功运行。

也可以直接通过Python加载模块来运行:

编译成pyc

python -m py_compile 源代码

编译成pyo

python -O -m py_compile 源代码

这确实可以简单地保护我们的代码,同时似乎看起来像是加密的效果,但是要注意,这不是加密,只是把源码变成优化后的字节码而已,如果想要获得源码,我们一样可以通过逆向编译来得到源码,目前有专门逆向Python字节码的工具存在。

如果需要编译整个目录内的所有源代码,请参考Python compileall

我算是白学Python了,现在才知道原来Python是可以编译的