Windows:pyd文件
Linux:so文件
import subprocess, re
import sys, os, shutil, time
from distutils.core import setup
from Cython.Build import cythonize
import platform
starttime = time.time()
currdir = os.path.abspath('.') # 当前目录
parentpath = sys.argv[1] if len(sys.argv) > 1 else ""
setupfile = os.path.join(os.path.abspath('.'), __file__)
build_dir = currdir + "/build" # 构建目录
build_tmp_dir = build_dir + "/temp" # 临时目录
def getpy(basepath=os.path.abspath('.'), parentpath='', name='', excepts=(), copyOther=False, delC=False):
"""
获取py文件的路径
:param basepath: 根路径
:param parentpath: 父路径
:param name: 文件/夹
:param excepts: 排除文件
:param copy: 是否copy其他文件
:return: py文件的迭代器
"""
fullpath = os.path.join(basepath, parentpath, name)
for fname in os.listdir(fullpath):
ffile = os.path.join(fullpath, fname)
if os.path.isdir(ffile) and fname != build_dir and not fname.startswith('.'):
for f in getpy(basepath, os.path.join(parentpath, name), fname, excepts, copyOther, delC):
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 os.path.realpath(ffile) != os.path.realpath(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)
elif copyOther:
dstdir = os.path.join(basepath, build_dir, parentpath, name)
if not os.path.isdir(dstdir):
os.makedirs(dstdir)
shutil.copyfile(ffile, os.path.join(dstdir, fname))
else:
pass
def getc(basepath=os.path.abspath('.'), parentpath='', name=''):
"""
获取c文件的路径
:param basepath: 根路径
:param parentpath: 父路径
:param name: 文件/夹
:return: py文件的迭代器
"""
fullpath = os.path.join(basepath, parentpath, name) # 本级目录
for fname in os.listdir(fullpath): # fname 所有文件
ffile = os.path.join(fullpath, fname) # 所有文件及绝对路径
if os.path.isdir(ffile): # 获得不是build目录和.开头的目录
for f in getc(basepath, os.path.join(parentpath, name), fname):
yield f
elif os.path.isfile(ffile): # 同级的文件
yield os.path.join(basepath, parentpath, name, fname)
else:
pass
def GetDefaultPath():
"""
获取默认的python路径,目前只使用与windows
"""
path = os.environ['path']
lst = path.split(';')
for dir in lst:
try:
files = os.listdir(dir)
for file in files:
if file == "python.exe":
return dir
except:
pass
def chkCython(path):
'''
检查是否安装了cython
'''
path += "\Scripts"
files = os.listdir(path)
for file in files:
if file == "cython.exe":
return True
return False
def getLibName(path):
"""
得到python的库名(如 python36)
"""
path += '\libs'
for fp in os.listdir(path):
rtn = re.match(r'python...lib', fp)
if rtn is not None:
return fp[:len(fp) - 4]
def check_system():
system_name = platform.system()
return system_name
def packPydFiles():
"""
打包pyd文件
"""
sys_name = check_system()
module_list = list(getpy(basepath=currdir, parentpath=parentpath, excepts=(setupfile)))
if sys_name == "Windows":
pythonPath = GetDefaultPath()
res = (cythonize(module_list, build_dir=build_dir))
cfile_list = list(getc(basepath=build_dir))
if chkCython(pythonPath):
for i in cfile_list:
str_c = i
str_pyd = os.path.splitext(i)[0] + '.pyd'
libname = getLibName(pythonPath)
cmd = 'gcc {} -o {} -shared -DMS_WIN64 -I "{}\include" -L "{}\libs" -l {}'.format(str_c, str_pyd,
pythonPath,
pythonPath,
libname)
rtn2 = subprocess.run(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
os.remove(str_c)
else:
print('请安装cython模块')
elif sys_name == "Linux":
try:
setup(ext_modules=cythonize(module_list, build_dir=build_dir),
script_args=["build_ext", "-b", build_dir, "-t", build_tmp_dir])
except Exception as ex:
print("error:", ex)
module_list = list(getpy(basepath=currdir, parentpath=parentpath, excepts=(setupfile), delC=True))
if os.path.exists(build_tmp_dir):
shutil.rmtree(build_tmp_dir)
packPydFiles()