Cython编译python项目

Cython编译python项目

简介

cythonize 是 Cython 编译器的一个命令行工具,用于简化 Cython 扩展模块的构建过程。Cython 是一个用于编写 Python 扩展模块的工具,它允许在 Python 中使用 C 的语法和性能,同时保持 Python 的灵活性和易用性。

具体来说,cythonize 用于将 Cython 源文件(.pyx)编译成 C 代码,并最终构建为共享库或扩展模块,以供 Python 使用。这个工具的目标是提高性能,同时保持 Python 编码的简洁性和可读性。

安装

  • python 安装cython

    pip install cpython
    
  • linux 安装:python-devel,gcc

    yum install python-devel

    yum install gcc

单个文件编译

  • 命令行编译

    cythonize -i 文件名
    
  • 基于 setup.py

     from setuptools import setup
     from Cython.Build import cythonize
    
     setup(
         name = 'test',
         ext_modules = cythonize("test.pyx"),
         zip_safe = False,
     )
    
    python setup.py build_ext --inplace
    

编译整个项目

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

执行前提:
     系统安装python-devel 和 gcc
     Python安装cython
 
编译整个当前目录:
     python py-setup.py
编译某个文件夹:
     python py-setup.py BigoModel
 
生成结果:
     目录 build 下
 
生成完成后:
     启动文件还需要py/pyc担当,须将启动的py/pyc拷贝到编译目录并删除so文件
 
"""
 
import sys, os, shutil, time
from distutils.core import setup
from Cython.Build import cythonize
 
starttime = time.time()
currdir = os.path.abspath('.')
if len(sys.argv) >= 2:    
    path_list = sys.argv[1:]
else:
    path_list = ['.']
print("======")
print("build path:", path_list)
print("======")
#parentpath = sys.argv[1] if len(sys.argv)>1 else ""
#if parentpath == '':
#    print("Error:CopyDir is null!")
#    sys.exit(1)

setupfile= os.path.join(os.path.abspath('.'), __file__)
build_dir = "build"
build_tmp_dir = build_dir + "/temp"
 
def getpy(parentpath='', name='', excepts=(), copyOther=False,delC=False, except_fname=()):
    """
    获取py文件的路径
    :param parentpath: 父路径
    :param name: 文件/夹
    :param excepts: 排除文件
    :param copyOther: 是否copy其他文件
    :param delC: 是否删除C文件
    :param except_fname: 排除的文件名
    :return: py文件的迭代器
    """
    fullpath = os.path.join(parentpath, name)
    for fname in os.listdir(fullpath):
        if fname in except_fname:
            continue
        ffile = os.path.join(fullpath, fname)
        #print('{}\n{}\n{}'.format(parentpath, name, fname))
        #print('-----')
        if os.path.isdir(ffile) and fname != build_dir and not fname.startswith('.'):
            if fname == "__pycache__":
                continue
            for f in getpy(os.path.join(parentpath, name), fname, excepts, copyOther, delC, except_fname):
                yield f
        elif os.path.isfile(ffile):
            ext = os.path.splitext(fname)[1]
            if ext == ".c":
                if delC and os.stat(ffile).st_mtime > starttime:
                    os.remove(ffile)
            elif ffile not in excepts and os.path.splitext(fname)[1] not in('.pyc', '.pyx'):
                if os.path.splitext(fname)[1] in('.py', '.pyx') and not fname.startswith('__'):
                    yield os.path.join(parentpath, name, fname)
                if fname == '__init__.py' and copyOther:
                    dstdir = os.path.join(build_dir, parentpath, name)
                    if not os.path.isdir(dstdir): 
                        os.makedirs(dstdir)
                    shutil.copyfile(ffile, os.path.join(dstdir, fname))
            if copyOther:
                if ffile in excepts:
                    continue
                exclude_suffix = ('.pyc', '.pyx', '.py', '.c')
                if os.path.splitext(fname)[1] in exclude_suffix\
                    or fname.startswith('__'):
                    continue
                dstdir = os.path.join(build_dir, parentpath, name)
                if not os.path.isdir(dstdir): 
                    os.makedirs(dstdir)
                shutil.copyfile(ffile, os.path.join(dstdir, fname))
        else:
            print('#pass [%s]...'%(ffile))
            pass


if __name__ == "__main__": 
    
    for parentpath in path_list:
        #获取py列表
        module_list = list(getpy(parentpath=parentpath, excepts=(setupfile), except_fname=("jupyter_config.py")))
        print(module_list)
        try:
            setup(ext_modules = cythonize(module_list, language_level=3),
               script_args=["build_ext", "-b", build_dir, "-t", build_tmp_dir]
               )
        except Exception as e:
             print (e)
        else:
             module_list = list(getpy(parentpath=parentpath, excepts=(setupfile), copyOther=True))
        module_list = list(getpy(parentpath=parentpath, excepts=(setupfile), delC=True))
        if os.path.exists(build_tmp_dir): 
            shutil.rmtree(build_tmp_dir)
        
        print('## setup [{}] over ...'.format(parentpath))
                
    print("complate! time:", time.time()-starttime, 's')

编译完成后,进行调用。

import main

app = main.app
app.run(host='0.0.0.0',port=8037)

猜你喜欢

转载自blog.csdn.net/qq128252/article/details/134837582