python字节码加密,使用pyc提升运行速度
之前项目有人提到pyc的问题,没有研究明白,这次搞清楚了.有什么问题可以留言给我#print。
最近在做一个项目使用python开发,但是在发布之后不能直接对外暴露源码,所以需要对python脚本加密,这个文章总结一下对加密的一些学习,分享给需要的同学
1、加密方法
在线上搜索和自己了解的一些东西,学习到有两种方法
-
直接使用pyc文件
-
使用pyarmor 加密
这两种方式是目前都测试过的,其他的方式没有深入研究就不分享了,感兴趣的可以自己找一下。今天先分享下使用pyc文件。
2、使用pyc文件
2.1 pyc文件是怎么回事
pyc 是 "Python Compiled" 的标准缩写,指代编译后的字节码文件,可以理解为Java 文件中的字节码文件。 python是解释型语言,运行速度比不上编译型语言,为了提升运行时效率,所以将python预编译为pyc文件。
2.2 pyc文件生成
在 Python 中,只有当文件被当作模块导入时,才会生成 pyc 文件。也就是说,Python 解释器认为,只有 import 进行的模块才需要被重用。生成 pyc 文件的好处显而易见,当我们多次运行程序时,不需要重新对该模块进行解释。

我这里使用的pycharm,在编辑器内看不到这个__pycache__文件夹,但是在文件浏览器中可以看到,这是因为pycharm默认隐藏了。 怎么手动生成这个__pycache__?
-
对单个文件生成
python -m py_compile example.py
-
对项目内所有的python生成
1.将当前项目的所有代码生成pyc
python -m compileall .
-
使用python脚本生成
import py_compile
py_compile.compile('example.py', optimize=2) # optimize=2 表示进一步移除文档字符串
2.3 移除源码,使用pyc执行
这也是我的主要目的,就是不暴露源码,使用pyc文件。 编译完之后,会在源码的同级目录下生成__pycache__文件夹。 生成的文件名为 hy_concent.cpython-311.pyc, 最初以为只要把源码删除之后,自动会执行__pycache__ 内的pyc,并不是这样,需要做一些处理才能使用。
1.生成pyc文件
2.对pyc文件重命名,去除python的版本号
3.替换源码所在位置
2.4 工具脚本
上面三步很重要,但是如果项目比较复杂,文件夹套文件夹这时候就麻烦了,手动操作不现实,所以搞了一个脚本
import os
import sys
import shutil
from py_compile import compile
#print "argvs:",sys.argv
if len(sys.argv) == 3:
comd = sys.argv[1] #输入的命令
path = sys.argv[2] #文件的地址
if os.path.exists(path) and os.path.isdir(path):
for parent,dirname,filename in os.walk(path):
for cfile in filename:
fullname = os.path.join(parent,cfile)
if comd == 'clean' and cfile[-4:] == '.pyc':
try:
os.remove(fullname)
print("Success remove file:%s" % fullname)
except:
print("Can't remove file:%s" % fullname)
if comd == 'compile' and cfile[-3:] == '.py': #在这里将找到的py文件进行编译成pyc,但是会指定到一个叫做__pycache__的文件夹中
try:
compile(fullname)
print("Success compile file:%s" % fullname)
except:
print("Can't compile file:%s" % fullname)
if comd == 'remove' and cfile[-3:] == '.py' and cfile != 'settings.py' and cfile != 'wsgi.py':
try:
os.remove(fullname)
print("Success remove file:%s" % fullname)
except:
print("Can't remove file:%s" % fullname)
if comd=='copy' and cfile[-4:] == '.pyc':
parent_list = parent.split("\\")[:-1]
parent_up_path = ''
for i in range(len(parent_list)):
parent_up_path+=parent_list[i]+'\\'
shutil.copy(fullname,parent_up_path)
print(f'Copying {fullname} to {parent_up_path}')
print('update the dir of file successfully')
if comd=='cpython' and cfile[-4:] =='.pyc':
cfile_name = ''
cfile_list = cfile.split('.')
for i in range(len(cfile_list)):
if cfile_list[i]=='cpython-311':
continue
cfile_name+=cfile_list[i]
if i==len(cfile_list)-1:
continue
cfile_name+='.'
shutil.move(fullname,os.path.join(parent,cfile_name))
print('update the name of the file successfully')
else:
print("Not an directory or Direcotry doesn't exist!")
else:
print("Usage:")
print("\tpython compile_pyc.py clean PATH\t\t#To clean all pyc files")
print("\tpython compile_pyc.py compile PATH\t\t#To generate pyc files")
print("\tpython compile_pyc.py remove PATH\t\t#To remove py files")
将脚本放在合适的位置,直接操作就行了
2.5 一些问题
-
pyc文件和python版本绑定
-
pyc文件可以被反编译,保密性差了些
总结
之前项目有人提到pyc的问题,没有研究明白,这次搞清楚了.
有什么问题可以留言给我
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)