最近在做一个项目使用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的问题,没有研究明白,这次搞清楚了.

有什么问题可以留言给我

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐