温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Python编译相关知识有哪些

发布时间:2021-09-08 14:58:37 来源:亿速云 阅读:103 作者:小新 栏目:大数据

小编给大家分享一下Python编译相关知识有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

Python是一门能快速开发的解释型语言

Python和Java的解释方式对比

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

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

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

编译源代码有以下作用:

  1. 源代码保护(算法保护)

  2. 防止用户篡改源代码解释器加载代码速度加快

Python的几种文件类型

py:Python控制台程序的源代码文件

pyw:Python带用户界面的源代码文件

pyx:Python包源文件

pyc:Python字节码文件

pyo:Python优化后的字节码文件

pyd:Python的库文件(Python版DLL)、在Linux上是so文件

pyc和pyo的生成方法

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

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

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

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

我们要用到的是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

optimize:优化字节码级别

optimize为1时,优化字节码级别为最高

-1和0:设置pyc优化级别

1和2:设置pyo优化级别

数字越小,优化级别越高

准备源文件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)

运行后可以看到已经成功编译成字节码文件了,分别为a.pyc和b.pyo。

尝试运行这2个字节码文件:

python a.pyc
python a.pyo

字节码文件成功运行。

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

#编译成pyc

python -m py_compile 源代码

#编译成pyo

python -O -m py_compile 源代码

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

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

pyd可以让我们的代码更安全

如果真的想要保护代码,为何不考虑把它变成python扩展模块?(目前还没有pyd被反编译的消息)

pyd是Python中的扩展模块,相当于windows的dll,不同的是pyd只供python调用而已。

实际上,大部分的包、小模块都是以pyd形式发布的。

如果特别感兴趣的小伙伴可以深入研究下setuptools和distutils

在把源代码转换成功pyd之前,我们需要用到Cython包。

pip list | findstr "Cython"

检查是否安装了Cython,没有请pip install Cython安装即可

编译pyd步骤1:生成C代码

import Cython.Build

#导入Build模块

Cython.Build.cythonize("a.py")

#a.py转换成C代码

cythonize运行完成之后,无异常的情况下会在a.py的目录下创建一个a.c文件,同时会返回一个distutils.extension.Extension对象列表

一定要注意的是:如果在Python Shell测试,一定要用绝对路径,否则会ValueError异常,cythonize不会从sys.path中读路径。

编译pyd步骤2:利用distutils生成pyd扩展模块

此时我们可以用distutils包来编译成我们要的pyd模块

编译a.py成pyd

import Cython.Build

import distutils.core

a = Cython.Build.cythonize("a.py")

#返回distutils.extension.Extension对象列表

distutils.core.setup(

name = 'pyd的编译',#包名称

version = "1.0",#包版本号

ext_modules= a,#扩展模块

author = "Happyran", #作者

author_email='happyran163@163.com' #作者邮箱

)

python 执行编译的脚本 build

python 执行编译的脚本 build_ext

此时会在编译脚本所在目录生成一个build目录,里面存着C语言的.def文件和.o文件,还有我们要的pyd文件

批量编译pyd文件的误区

此时我们已经生成了1个pyd文件,如果我们是扩展包/模块的开发者,怎么批量编译呢?

总有人会犯错,例如以下2个例子:

a = Cython.Build.cythonize("a.py")

b = Cython.Build.cythonize("b.py")

distutils.core.setup(

...,

ext_modules= [a,b]

)

这样做吗?NO......

a = Cython.Build.cythonize("a.py")

a.append(Cython.Build.cythonize("b.py"))

distutils.core.setup(

...,

ext_modules= a

)

还是这样?

犯这样的错原因却是因为:

a = Cython.Build.cythonize("a.py")

type(a)

提示<class 'list'>

没错,Cython.Build.cythonize返回的是一个列表,里面只有1个distutils.extension.Extension对象

会报错,需要1个Extension或者是2个元组

批量编译pyd

方法1:提取我们要的Extension对象

import Cython.Build

import distutils.core

a = Cython.Build.cythonize("a.py")[0] #提取Extension对象

b = Cython.Build.cythonize("b.py")[0]

distutils.core.setup(

name = 'pyd的编译', #包名称

version = "1.0", #包版本号

ext_modules= [a,b], #被扩展的模块

author = "Happyran", #作者

author_email='happyran163@163.com' #作者邮箱

)

方法2:转换成C代码后再进行Extension对象实例化

import Cython.Build

import distutils.core

Cython.Build.cythonize("a.py")

Cython.Build.cythonize("b.py")

distutils.core.setup(

name = 'pyd的编译', #包名称

version = "1.0", #包版本号

ext_modules= [distutils.core.Extension('a',["a.c"]),distutils.core.Extension('b', ['b.c'])], #被扩展的模块

#[

#distutils.core.Extension('a',["a.c"]),

#distutils.core.Extension('b', ['b.c'])

#]

author = "Happyran", #作者

author_email='happyran163@163.com' #作者邮箱

)

pyc和pyo相对而言安全性较低,pyd是目前解决Python开发中代码安全性最优的一个方案。

但是要注意一点:无论是pyc还是pyo、pyd,都是跟着Python版本走的,不要指望Python2.7的东西在Python3上完美运行。

PS:如果遇到running build...提示,删掉build目录重新编译即可。

以上是“Python编译相关知识有哪些”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI