将下述代码保存为setup.py
至需打包项目根目录,安装cython
后执行python setup.py
即可打包。
import sys, os, shutil, time
from distutils.core import setup
from Cython.Build import cythonize
start_time = time.time()
curr_dir = os.path.abspath('.')
parent_path = sys.argv[1] if len(sys.argv) > 1 else ""
setup_file = __file__.replace('/', '\\')
build_dir = "build"
build_tmp_dir = build_dir + "/temp"
s = "# cython: language_level=3"
def get_py(base_path=os.path.abspath('.'), parent_path='', name = '', excepts=(), copyOther=False, delC = False):
"""
获取py文件的路径
:param base_path: 根路径
:param parent_path: 父路径
:param excepts: 排除文件
:return: py文件的迭代器
"""
full_path = os.path.join(base_path, parent_path, name)
for filename in os.listdir(full_path):
full_filename = os.path.join(full_path, filename)
if os.path.isdir(full_filename) and filename != build_dir and not filename.startswith('.'):
for f in get_py(base_path, os.path.join(parent_path, name), filename, excepts, copyOther, delC):
yield f
elif os.path.isfile(full_filename):
ext = os.path.splitext(filename)[1]
if ext == ".c":
if delC and os.stat(full_filename).st_mtime > start_time:
os.remove(full_filename)
elif full_filename not in excepts and os.path.splitext(filename)[1] not in ('.pyc', '.pyx'):
if os.path.splitext(filename)[1] in ('.py', '.pyx') and not filename.startswith('__'):
path = os.path.join(parent_path, name, filename)
yield path
else:
pass
def pack_pyd():
# 获取py列表
module_list = list(get_py(base_path=curr_dir, parent_path=parent_path, excepts=(setup_file,)))
try:
setup(
ext_modules=cythonize(module_list, compiler_directives={'language_level': "3"}),
script_args=["build_ext", "-b", build_dir, "-t", build_tmp_dir],
)
except Exception as ex:
print("error! ", str(ex))
else:
module_list = list(get_py(base_path=curr_dir, parent_path=parent_path, excepts=(setup_file,), copyOther=True))
module_list = list(get_py(base_path=curr_dir, parent_path=parent_path, excepts=(setup_file,), delC=True))
if os.path.exists(build_tmp_dir):
shutil.rmtree(build_tmp_dir)
print("complate! time:", time.time() - start_time, 's')
def delete_c(path='.', excepts=(setup_file,)):
'''
删除编译过程中生成的.c文件
:param path:
:param excepts:
:return:
'''
dirs = os.listdir(path)
for dir in dirs:
new_dir = os.path.join(path, dir)
if os.path.isfile(new_dir):
ext = os.path.splitext(new_dir)[1]
if ext == '.c':
os.remove(new_dir)
elif os.path.isdir(new_dir):
delete_c(new_dir)
if __name__ == '__main__':
try:
pack_pyd()
except Exception as e:
print(str(e))
finally:
delete_c()
Unable to find vcvarsall.bat
错误
需安装对应版本VC++
-
)
yum install python-devel gcc
,如果确定安装依赖,可以稍微等一等,Linux内存不足编译稍大型文件会要很长时间
import
(如A文件首行调用B,B首行调用A,默认解释器执行不会出错,编译后会出错)
__init__.py
文件用于判断路径,如果有非空的__init__.py
文件,记得打包后复制进对应文件夹
__init__.py
判断路径打包和import
相对路径绝对路径复用,某些情况下打包后会出现无法定位某些模块的奇怪问题