项目交付的时候,为了加密源码,将py文件编译为.so文件。
1. 单个py文件编译
单个文件的编译方法如下,在setup.py文件中编写下列代码,使用命令:python3 setup.py build_ext,执行编译命令
from Cython.Build import cythonize
from distutils.core import setup
import os
path = ''
files = os.listdir(path)
source_files = []
for i in files:
if '.py' in i:
source_files.append(i)
setup(ext_modules = cythonize(source_files))
在setup.py的同一目录生成一个build文件夹,可以发现build目录下生成了一系列的.so文件。
将原始的py文件删掉,将so文件复制到对应的目录,直接使用:import ??进行调用即可,与py的调用方法一致。
2. 多个py文件(package目录)编译为一个so文件
一个py文件对应一个so文件是比较简单的,但是,当我们希望将多个py文件编译到一个so文件时,还需要进行其它处理。
工程的目录如下,需求是将entry中的三个py文件编译为一个so文件,并进行调用。
在setup.py文件中编写下列代码:
from setuptools import setup, find_packages, Extension
from Cython.Build import cythonize
sourcefiles = ['entry/bootstrap.py', 'entry/needle_sim.py', 'entry/parse_goods_name.py']
extensions = cythonize(Extension(
name="entry.bootstrap",
sources=sourcefiles,
))
kwargs = {
'name': 'entry',
'packages': find_packages(),
'ext_modules': extensions,
}
setup(**kwargs)
在bootstrap.py文件中编写下列代码,CythonPackageMetaPathFinder()的目的是:若import的包是以“entry.”开头,则从编译出的so文件中找到这个module并返回;bootstrap_cython_submodules()的目的是:将找到的这个module加入mete_path中,以便python执行时能够调用。
import sys
import importlib
# Chooses the right init function
class CythonPackageMetaPathFinder(importlib.abc.MetaPathFinder):
def __init__(self, name_filter):
super(CythonPackageMetaPathFinder, self).__init__()
self.name_filter = name_filter
def find_module(self, fullname, path):
if fullname.startswith(self.name_filter):
# use this extension-file but PyInit-function of another module:
return importlib.machinery.ExtensionFileLoader(fullname, __file__)
# injecting custom finder/loaders into sys.meta_path:
def bootstrap_cython_submodules():
sys.meta_path.append(CythonPackageMetaPathFinder('entry.'))
在__init__.py文件中编写下列代码:
# bootstrap is the only module which
# can be loaded with default Python-machinery
# because the resulting extension is called `bootstrap`:
from . import bootstrap
# injecting our finders into sys.meta_path
# after that all other submodules can be loaded
bootstrap.bootstrap_cython_submodules()
使用命令:python3 setup.py build_ext install,执行编译命令,可以发现,在python的系统依赖包目录下,生成了一个egg文件,其中包含了我们需要的bootstrap.so文件。
但是,调用并未成功,报错entry.needle_sim未找到,研究了2天无果。