上一篇介绍了【python源码加密】Cython方案讲解及简单示例,这篇着重介绍,对于python工程的多级目录如何进行Cython编译以及使用(文章末尾有获取源码方式)
Cython编译的问题
不支持同名文件:Cython编译的时候,同名文件只能打包一个pyd,那就必须一个文件夹一个文件夹的编译
- 不支持package:由于同名问题,而python在识别package的时候靠的是__init__.py
- 不支持原地生成:python setup.py build_ext --inplace 生成的pyd文件都在同个目录下
- 路径不能过长,路径过程容易出错
解决办法
我们可以通过一些逻辑制作一个打包脚本,用来解决以上的问题,脚本的逻辑如下:
- 将需要打包的整个源目录整个复制出来,形成目标目录
- 除了__init__.py外,编译其他的 .py文件,使用命令 cythonize -i xx.py
- 清理掉所有的中间文件以及除了__init__.py外的.py源码文件
- 将目标文件夹改名成源文件夹就可以使用了
示例
我的源码工程目录结构如下:
.
└── cython_module_2
├── f2
│ ├── f2_1
│ │ ├── fun2_1.py
│ │ └── __init__.py
│ ├── fun21.py
│ ├── fun22.py
│ └── __init__.py
├── f3
│ ├── fun31.py
│ └── __init__.py
├── f.py
└── __init__.py
通过编写pack_cpython.py脚本完成对该目录cython_module_2的cython编译:
# -*- coding: UTF-8 -*-
import shutil
import sys
import os
import subprocess
def clearzj(path):
files = os.listdir(path)
for fd in files:
cur_path = os.path.join(path, fd)
if os.path.isdir(cur_path):
if fd == '__pycache__' or fd == 'build':
shutil.rmtree(cur_path)
else:
clearzj(cur_path)
else:
_, ext = os.path.splitext(cur_path)
if ext == '.c' or ext == '.py':
if '__init__' not in cur_path:
os.remove(cur_path)
# 获取文件夹下所有的.py文件, 文件夹可以是多层级的
def find_py_files(folder):
py_files = []
for item in os.listdir(folder):
item_path = os.path.join(folder, item)
if os.path.isfile(item_path):
if item.endswith('.py'):
py_files.append(item_path)
elif os.path.isdir(item_path):
py_files.extend(find_py_files(item_path))
return py_files
def pack_cython(src_path, dest_path):
# 1. 将需要打包的整个源目录整个复制出来,形成目标目录
if os.path.exists(dest_path):
shutil.rmtree(dest_path)
if os.path.exists(src_path):
shutil.copytree(src_path, dest_path)
if os.path.exists(dest_path) is False:
print(f'目标文件夹={dest_path}不存在!')
return
# 2. 除了__init__.py外,编译其他的 .py文件
py_files = find_py_files(dest_path)
for py in py_files:
if '__init__' not in py:
cmd = ["cythonize", "-i", py]
try:
subprocess.run(cmd, check=True)
except subprocess.CalledProcessError as e:
print("Cython编译失败:", e)
sys.exit(0)
# 3. 清理掉所有的中间文件以及除了__init__.py外的.py源码文件
clearzj(dest_path)
# 4. 将目标文件夹改名成源文件夹就可以使用了
if __name__ == "__main__":
src_folder = './cython_module_2'
dest_folder = f'{src_folder}_back'
pack_cython(src_folder, dest_folder)
执行 python pack_cython.py,完成编译,过程如下(windows和linux均可):
此时,编译完成后的目录如下:
我们直接对该包进行调用即可:
结束语
由于本人能力有限,难免有疏漏之处
文中源码文件【获取方式】:关注公众号:利哥AI实例探险
给公众号发送 cython打包示例1 获取下载方式,免费,无套路,关注即可!!!