使用 cython
将 python
编译成 so
加密
准备
cython 环境
pip install cython
yum install -y gcc python-devel
测试代码
testc.py
import os
def realpath():
print os.path.realpath('.')
将 testc.py
copy 到 /usr/lib/python2.7/site-packages/
,py 测试
[root@vm-21b-01vnm pycompile]# python
Python 2.7.5 (default, Aug 4 2017, 00:39:18)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-16)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import testc
>>> testc.realpath()
/root/pycompile
>>>
手工编译
# cd /usr/lib/python2.7/site-packages/
# mv testc.pyc /tmp/
# cython testc.py
# ll | grep testc
-rw-r--r-- 1 root root 128660 Oct 11 10:13 testc.c
-rw-r--r-- 1 root root 60 Oct 11 10:10 testc.py
# gcc -c -fPIC -I/usr/include/python2.7/ testc.c
# ll | grep testc
-rw-r--r-- 1 root root 128660 Oct 11 10:13 testc.c
-rw-r--r-- 1 root root 46168 Oct 11 10:13 testc.o
-rw-r--r-- 1 root root 60 Oct 11 10:10 testc.py
# gcc -shared testc.o -o testc.so
# ll | grep testc
-rw-r--r-- 1 root root 128660 Oct 11 10:13 testc.c
-rw-r--r-- 1 root root 46168 Oct 11 10:13 testc.o
-rw-r--r-- 1 root root 60 Oct 11 10:10 testc.py
-rwxr-xr-x 1 root root 47544 Oct 11 10:13 testc.so
# ll | grep testc
-rw-r--r-- 1 root root 128660 Oct 11 10:13 testc.c
-rw-r--r-- 1 root root 46168 Oct 11 10:13 testc.o
-rw-r--r-- 1 root root 60 Oct 11 10:10 testc.py
-rwxr-xr-x 1 root root 47544 Oct 11 10:13 testc.so
# mv testc.c testc.o testc.py /tmp/
# ll | grep testc
-rwxr-xr-x 1 root root 47544 Oct 11 10:13 testc.so
测试
# python
Python 2.7.5 (default, Aug 4 2017, 00:39:18)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-16)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import testc
>>> testc.realpath()
/usr/lib/python2.7/site-packages
自动编译
方法一
将 testc.py
移动到 /usr/lib/python2.7/site-packages/testc
目录下,创建 setup.py
文件:
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules = cythonize("testc.py")
)
运行:
# ll
total 8
-rw-r--r-- 1 root root 119 Oct 11 10:18 setup.py
-rw-r--r-- 1 root root 60 Oct 11 10:10 testc.py
# python setup.py build_ext --inplace
Compiling testc.py because it changed.
[1/1] Cythonizing testc.py
running build_ext
building 'testc' extension
gcc -pthread -fno-strict-aliasing -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -I/usr/include/python2.7 -c testc.c -o build/temp.linux-x86_64-2.7/testc.o
creating build/lib.linux-x86_64-2.7
gcc -pthread -shared -Wl,-z,relro build/temp.linux-x86_64-2.7/testc.o -L/usr/lib64 -lpython2.7 -o build/lib.linux-x86_64-2.7/testc.so
copying build/lib.linux-x86_64-2.7/testc.so ->
# ll
total 228
drwxr-xr-x 3 root root 35 Oct 11 10:19 build
-rw-r--r-- 1 root root 119 Oct 11 10:18 setup.py
-rw-r--r-- 1 root root 128849 Oct 11 10:19 testc.c
-rw-r--r-- 1 root root 60 Oct 11 10:10 testc.py
-rwxr-xr-x 1 root root 91448 Oct 11 10:19 testc.so
#
方法二
创建 setup.py
#!/usr/bin/env python
'''
ref:
https://cython.readthedocs.io/en/latest/src/userguide/source_files_and_compilation.html
how to use:
python setup.py build_ext --inplace
'''
import os
from distutils.core import setup, Extension
from Cython.Build import cythonize
exclude_files = ["__init__.py", "models.py"]
exclude_folders = ["migrations"]
include_folders = ["home_application"]
build_dir = "build"
build_tmp_dir = build_dir + "/temp"
root_path = os.getcwd()
# get need cythonize files, format like: ["<path>/<file1.py>", "<path>/<file2.py>"]
py_files = []
def _folder_files(root_dir):
for root, dirs, files in os.walk(root_dir):
relative_paths = root.replace(root_path, "").lstrip(os.sep)
name = relative_paths.replace(os.sep, ".")
is_exclude_folder = False
for _ef in exclude_folders:
if _ef in name:
is_exclude_folder = True
break
if is_exclude_folder:
continue
for f in files:
if f not in exclude_files and f.endswith(".py"):
py_files.append(os.path.join(relative_paths, f))
def get_files():
for include_folder in include_folders:
root_dir = os.path.join(root_path, include_folder)
_folder_files(root_dir)
# if __name__ == '__main__':
# get_files()
# for i in py_files:
# print i
try:
get_files()
# extensions = []
# for i in files:
# extensions.append(Extension(i[0], i[1]))
ext_modules = cythonize(py_files)
except ImportError:
ext_modules = None
setup(
ext_modules=ext_modules,
script_args=["build_ext", "-b", build_dir, "-t", build_tmp_dir]
)
执行:
python setup.py build_ext --inplace
注意:
- 使用不同的
python
编译,会存在不兼容现象,需要清理pyc
文件:find . -type f -name "*.pyc" | xargs -n1 rm
- cp -r build/<..>/* .
- find . -type f -name “*.c” | xargs -n1 rm
- find . -type f -name “*.py” | grep -v “init.py” | grep -v “migrations” | grep -v “models.py” | xargs -n1 rm
扩展
pip install -U pyinstaller
pip install pyinstaller -i https://mirrors.aliyun.com/pypi/simple/
pyinstaller your_program.py
pyinstaller -F -w your_program.py