Python源文件编译为动态链接库文件

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()
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容