首页 > 编程知识 正文

将python转化为c,java 动态生成类

时间:2023-05-06 20:37:01 阅读:38888 作者:1585

最近,作者遇到了一个需要将Python工程引入另一个集群,但必须确保Python代码安全的需求。 于是在网上搜索,找到了几种解决方案,但都不符合需求。 综合检索了几种解决方案,最终作者以编译成so动态库的方式公开。

首先,找到了一些解决方案及其优缺点

编译成pyc发布

优点:操作简单

缺点:可以反编译

cx_freeze

好处:在部署到新环境中时非常有用,因为freeze命令可以直接在二进制中生成项目的所有依赖关系

缺点: freeze命令在工程项目大时非常慢,其生成的Python代码实际上也是pyc,可以反向编译

极简

优点:代码混淆保护代码

缺点:似乎只影响单个文件的混淆,但在一个工程项目中行不通

cython被编译成动态库

优点可以将:代码编译成. so动态库,起到代码保护的作用

缺点:编译速度太慢了

综合这些优缺点,作者最终选择了用cython编译成动态库的方式,达到了保护Python代码的目的,cython官方文档

:说明具体做法和原理

cython首先将python代码翻译成c语言代码,然后cython将其编译成. so动态库。 最后,使用编译的build/lib.linux-x86_64-2.7 (此目录因平台和python版本而异。 作者的是linux平台,python版本

但是,这里有个洞。 编译Python库时,build/lib.linux-x86_64-2.7中的库文件需要每个库的__init__.py文件。 因此,以下代码首先创建空的__文件,然后查找所有. py文件并将其编译到动态库中,并将除. py之外的所有文件移动到原始目录中的相应位置。 以下是相应的转换后的setup.py文件和示例

setup.py文件的源代码

#! /usr/易怒的时间/env python

#-* -编码: utf-8-* -

# @File : setup.py

# @Time : 2018/12/04

# @ author : spx CDs (spx CDs @ Gmail.com) )。

导入操作系统

导入系统

导入shutil

导入编号

导入模板文件

来自设置工具导入设置

from setup tools.extensionimportextension

fromcython.buildimportcythonize

fromcython.distutilsimportbuild _ ext

导入平台

build _ root _ dir=‘build/lib .‘platform.system (.lower )、‘-‘platform.machine’和‘-‘str’。

sys.version _ info.major (.‘str’sys.version _ info.major ) )。

打印(build _ root _ dir )是

扩展=[ ]

ignore _ folders=[‘build’,‘test’,‘tests’]

conf_folders=[‘conf‘]

defget _ root _ path (根) :

ifOS.path.dirname(root ) in )、)、)、) :

return OS.path.basename (根)

else:

返回get _ root _ path (OS.path.dirname ) root ) )

defcopy_file(src,dest ) :

ifOS.path.exists(dest ) :

返回

ifno tos.path.exists (OS.path.dirname ) dest ) ) :

操作系统. makedirs (操作系统. path.dirname ) (dest ) )

IFOS.Path.Isdir(src ) :

shutil.copytree(src,dest ) )。

else:

shutil.copyfile(src,dest ) )。

def touch_init_file () :

init _ file _ name=OS.path.join (tem

pfile.mkdtemp(), ‘__init__.py‘)

with open(init_file_name, ‘w‘):

pass

return init_file_name

init_file = touch_init_file()

print(init_file)

def compose_extensions(root=‘.‘):

for file_ in os.listdir(root):

abs_file = os.path.join(root, file_)

if os.path.isfile(abs_file):

if abs_file.endswith(‘.py‘):

extensions.append(Extension(get_root_path(abs_file) + ‘.*‘, [abs_file]))

elif abs_file.endswith(‘.c‘) or abs_file.endswith(‘.pyc‘):

continue

else:

copy_file(abs_file, os.path.join(build_root_dir, abs_file))

if abs_file.endswith(‘__init__.py‘):

copy_file(init_file, os.path.join(build_root_dir, abs_file))

else:

if os.path.basename(abs_file) in ignore_folders:

continue

if os.path.basename(abs_file) in conf_folders:

copy_file(abs_file, os.path.join(build_root_dir, abs_file))

compose_extensions(abs_file)

compose_extensions()

os.remove(init_file)

setup(

name=‘my_project‘,

version=‘1.0‘,

ext_modules=cythonize(

extensions,

nthreads=16,

compiler_directives=dict(always_allow_keywords=True),

include_path=[numpy.get_include()]),

cmdclass=dict(build_ext=build_ext))

# python setup.py build_ext

下面是一个例子

目录结构是这样子的

.

├── main.py

├── mypkg

│   ├── foo.py

│   ├── __init__.py

│   └── t

│   ├── __init__.py

│   └── t.py

└── setup.py

然后运行命令python setup.py build_ext 即可看到新的目录结构

├── build

│   ├── lib.linux-x86_64-2.7

│   │   ├── main.so

│   │   ├── mypkg

│   │   │   ├── foo.so

│   │   │   ├── __init__.py

│   │   │   ├── __init__.so

│   │   │   └── t

│   │   │   ├── __init__.py

│   │   │   ├── __init__.so

│   │   │   └── t.so

│   │   └── setup.so

│   └── temp.linux-x86_64-2.7

│   ├── main.o

│   ├── mypkg

│   │   ├── foo.o

│   │   ├── __init__.o

│   │   └── t

│   │   ├── __init__.o

│   │   └── t.o

│   └── setup.o

├── main.c

├── main.py

├── mypkg

│   ├── foo.c

│   ├── foo.py

│   ├── __init__.c

│   ├── __init__.py

│   └── t

│   ├── __init__.c

│   ├── __init__.py

│   ├── t.c

│   └── t.py

├── setup.c

└── setup.py

然后, 将main.py拷贝到build/lib.linux-x86_64-2.7 直接就可以运行了

.

├── main.py

├── main.so

├── mypkg

│   ├── foo.so

│   ├── __init__.py

│   ├── __init__.so

│   └── t

│   ├── __init__.py

│   ├── __init__.so

│   └── t.so

└── setup.so

$ cat main.py

from mypkg.foo import hello

from mypkg import fun1

from mypkg.t.t import t

if __name__ == ‘__main__‘:

hello()

fun1()

t()

$ python main.py

this is in hello

this is in fun1

this is in t

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。