The result of tag: (1 results)

一种使用Cython保护Python源代码的方法

by LauCyun Sep 05,2017 09:55:06 20,191 views

最近,有一个Python项目需要保护整个代码库,毕竟Python编译的pyc很容易被人反编译回来,所以使用Cython进行编译处理。

实际上属于一种代码混淆/加密的技术,原理相当于将python编译成C,然后再转成.so(Windows下为.pyd)文件。.so文件为动态连结库,可以在程序运行时动态链接,类似于Windows的dll文件。

Cython是Python编程语言和扩展Cython编程语言(基于Pyrex)的静态编译器,它可以保护Pyhton源码和提高代码执行效率。详细可参考:

Cython安装非常方便,因为一般像Anaconda等都附带了,如果没有用这些,也可以自己安装。附上安装教程http://docs.cython.org/src/quickstart/install.html

源代码传送门:https://git.laucyun.com/myweb/blog-files/tree/master/mypkg

先来看一下代码库的结构:

.
├── HISTORY.rst
├── MANIFEST.in
├── README.txt
├── build.cmd
├── build.sh
├── entrypoint.py
├── mypkg
│   ├── __init__.py
│   ├── hello.py
│   ├── tools
│   │   ├── __init__.py
│   │   └── printf.py
│   └── version.py
├── requirements.txt
└── setup.py

需要对mypkg文件夹中的.py文件及子文件夹中的.py文件都编译成.so.pyd文件。

然后我们新建一个setup.py脚本,这个Python文件的目的就是使用Cython编译器去编译.py源文件,内容如下:

# -*- coding: utf-8 -*-

import os
import fileinput
import sys
from setuptools import setup, find_packages
from codecs import open
from Cython.Build import cythonize
from mypkg.version import __pkgname__, __version__

requires = []
require_file = 'requirements.txt'
if sys.platform.lower()[:3] == 'win':
    requires.append('pywin32>=219')
for line in fileinput.input(require_file):
    requires.append(line.replace('\n', ''))

packages = find_packages()

ext_modules = []
for (path, dirs, files) in os.walk("mypkg"):
    for filename in files:
        file = os.path.join(path, filename)
        if '__init__' != os.path.splitext(filename)[0] and '.py' == os.path.splitext(filename)[1]:
            ext_modules.append(file)

with open('HISTORY.rst', 'r', 'utf-8') as f:
    history = f.read()

setup(
    name=__pkgname__,
    version=__version__,
    author='laucyun<liu@laucyun.com>',
    author_email='',
    description='',
    long_description=history,
    url='-',
    packages=[],
    package_data={},
    include_package_data=True,
    scripts=['entrypoint.py'],
    entry_points={
        "console_scripts": ["%s=entrypoint:run" % __pkgname__]
    },
    package_dir={'mypkg': 'mypkg'},
    install_requires=requires,
    license='MIT',
    zip_safe=False,
    classifiers=[
        'Development Status :: 1 - Production/Stable',
        'Intended Audience :: Developers',
        'Natural Language :: English',
        'Operating System :: OS Independent',
        'Programming Language :: Python',
        'Programming Language :: Python :: 2.7',
        'Topic :: Software Development :: Libraries :: Python Modules',
    ],
    ext_modules=cythonize(ext_modules),
)

然后执行setup.py文件,命令如下:

python setup.py build_ext --inplace

build_ext大概就是编译extension文件的意思,inplace则是放到源代码.py旁边,也就是同一目录下的意思。

然后,就可以看到多了两个文件,一个是.c、一个是.so.pyd文件,如图1所示:


图1 Cython编译后代码库结构

这里,C文件就是Cython将我们的.py文件解析成一个C文件,不依赖与平台,而后面的.so.pyd文件,则是将C文件进行编译后的一个文件,依赖于平台。

这时,.so.pyd文件就可以像普通的python文件一样,被import

最后瞅一眼.so.pyd文件内容,如图2所示:


图2 .so.pyd文件内容

这样,就完成了对.py源代码的保护了。

...

Tags Read More