Cython kompiliert ein Python-Projekt
Cython kompiliert ein Python-Projekt
Einführung
cythonize
ist ein Befehlszeilentool für den Cython-Compiler, das den Erstellungsprozess von Cython-Erweiterungsmodulen vereinfacht. Cython ist ein Tool zum Schreiben von Python-Erweiterungsmodulen, das die Verwendung der Syntax und Leistung von C in Python ermöglicht und gleichzeitig die Flexibilität und Benutzerfreundlichkeit von Python beibehält.
Konkret
cythonize
wird verwendet, um Cython-Quelldateien (.pyx) in C-Code zu kompilieren und sie schließlich in gemeinsam genutzte Bibliotheken oder Erweiterungsmodule zur Verwendung durch Python einzubauen. Das Ziel dieses Tools besteht darin, die Leistung zu verbessern und gleichzeitig die Einfachheit und Lesbarkeit der Python-Codierung beizubehalten.
Installieren
-
Python installiert Cython
pip install cpython
-
Linux-Installation: Python-Devel, GCC
Lecker, installiere Python-Devel
Lecker, gcc installieren
Kompilierung einzelner Dateien
-
Befehlszeilenkompilierung
cythonize -i 文件名
-
Basierend auf 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
Kompilieren Sie das gesamte Projekt
# -*- 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')
Nachdem die Kompilierung abgeschlossen ist, führen Sie den Anruf durch.
import main
app = main.app
app.run(host='0.0.0.0',port=8037)