Cython批量编译py文件并打包python项目为whl

目录

1、Cython批量编译py文件

 2、生成whl文件

3、关于使用报错找不到模块


1、Cython批量编译py文件

Cython是一个编程语言,它通过类似Python的语法来编写C扩展并可以被Python调用。能够将Python+C混合编码的.pyx脚本转换为C代码,主要用于优化Python脚本性能或Python调用C函数库。基于它的原理,可以得到一种代码加密的思路:将 .py/.pyx 编译为 .c 文件,再将 .c 文件编译为 .so(Unix) 或 .pyd(Windows),这样得到的文件更难反编译。

优点

  • 生成的二进制 .so 或 .pyd 文件难以破解
  • 同时带来了性能提升

不足

  • 兼容性稍差,对于不同版本的操作系统,可能需要重新编译
  • 虽然支持大多数 Python 代码,但如果一旦发现部分代码不支持,完善成本较高

批量加密代码:

from setuptools import setup, find_packages
from Cython.Build import cythonize
import os


def print_files(path):
    '''
    循环遍历文件夹与文件
    :param path: 路径
    :return:
    '''
    for root, dirs, files in os.walk(path):
        for file in files:
            print(os.path.join(root, file))  # 打印完整路径
            print(file)  # 打印文件名
            print(os.path.splitext(file)[0])  # 打印无扩展名的文件名


filepaths = []


def encrypt_py(path):
    '''
    加密路径下除了__init__.py的所有.py文件
    :param path:路径
    :return:
    '''
    for root, dirs, files in os.walk(path):
        for file in files:
            fullpath = os.path.join(root, file)
            print(fullpath)  # 打印完整路径

            filepath = file
            print(filepath)  # 打印文件名

            filename = os.path.splitext(file)[0]
            print(filename)  # 打印无扩展名的文件名

            if filename == "__init__":
                continue

            suffix = os.path.splitext(file)[1].split('.')[-1]
            print(suffix)

            if suffix == "py":
                filepaths.append(fullpath)


encrypt_py(".\\autoTestPrj")
print(filepaths)
for f in filepaths:
    setup(ext_modules=cythonize(f))

使用以下命令在setup.py目录下执行: 

python setup.py build_ext --inplace

 build_ext参数是一个命令,指示distutils构建扩展对象或cythonize调用创建的对象。 可选的--inplace标志指示distutils将每个扩展模块放在其各自的Cython .pyx源文件旁边

Cython批量编译py文件并打包python项目为whl_第1张图片

注意:__init__.py不要加密,加密后打包为whl再安装无法识别到__init__.py,不会安装目录下的pyd文件!!

 2、生成whl文件

如果直接打包,会把没有加密过的源码也打包进去,安装时会一同安装,那加密就没有意义了。所以可以先移除.py文件,再打包。

代码如下:

from setuptools import setup, find_packages

setup(name='autoTestPrjencrypt',    #打包的名字最好不要有"-""_"等特殊字符,测试的时候发现有特殊字符可能存在找不到该模块的问题
      version='1.0.1',
      description='aaaaaa',
      author='aaaaaa',
      author_email='[email protected]',
      packages=find_packages(),
      include_package_data=True,
      # 将pyd文件打包进入
      package_data={
          '': ['*.pyd'],
      },
      )

 在cmd执行以下命令:

python setup.py bdist_wheel

 打包完成后可以在dist文件下看到whl文件:

此时再进行安装:

pip install autoTestPrjencrypt-1.0.1-py3-none-any.whl

 安装完成可以输入:

pip show package_name

 如果安装成功可以看到输出的包的信息和安装位置:

Cython批量编译py文件并打包python项目为whl_第2张图片

3、关于使用报错找不到模块

 此时使用可能会提示找不到该模块

解决1

我们可以打包前把.pyd名称去掉生成时生成的“.cp39-win_amd64”这一串字符,然后再执行步骤2,安装好后就可以正常使用了

解决2:

我的模块层次是这样的:

[项目文件夹]
│  globals.py
│  __init__.py
│
├─ocr
│  │  __init__.py
│  └─ imgtotxt.py
│
├─res
├─tests 
│  └─__init__.py
│
└──tool
   │  __init__.py
   └─ timetool.py

在orc/imgtotxt.py中我调用了tool/timetool.py中的函数,安装好之后报错找不到orc/imgtotxt.py导入tool/timetool.py的模块。

因为在imgtotxt.py中导入是这样写的,安装后找不到tool模块就会报错:

from tool.timetool import get_curtime

可以使用绝对导入,指定完整的路径就可以解决,但是如果层次比较多就不推荐使用这个:

from 项目名称.tool.timetool import get_curtime

尝试了sys.path.append,测试后还是有问题,不知道是不是哪里写错了:

import sys
sys.path.append("..")
from tool.timetool import get_curtime

 目前没有找到更好的解决办法,如果大家有的话可以在评论区告诉我,谢谢!!

真的很需要了!

4、测试导入

测试代码:

from autotestprjencrypt.ocr import imgtotxt
from autotestprjencrypt.tool import timetool

curtime=timetool.get_curtime()
print(curtime)
imgtotxt.ocr_img_text(saveimg=True, printResult=True)

 也能够正常运行:

Cython批量编译py文件并打包python项目为whl_第3张图片

ctrl+鼠标左键去看代码,可以看到是完全看不懂源代码的:

Cython批量编译py文件并打包python项目为whl_第4张图片

Cython批量编译py文件并打包python项目为whl_第5张图片

 加密ok!

使用ok!

参考:Python源码保护 - 知乎

你可能感兴趣的:(python,python,linux,wheel,windows)