最近项目上要求封装.so文件,其实很简单但也碰到了一些问题,本博客来总结一下,注意本文讨论的是ubuntu16.04下python3的情况。
例如你的文件夹包含了所有py文件,那很简单:
--root:
a.py
b.py
这时候写一个setup.py就好:
from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension
extensions = [
Extension("a",["a.py"]),
Extension("b",["b.py"]),
]
setup(ext_modules=cythonize(extensions))
然后执行python3 setup.py build_ext
生成的打包文件就在build/lib*/目录下,进入该目录后直接python3就可以import a了,或者在这个目录写一个demo.py文件执行并调用a或b,也可以完成任务。
那么下面要说一下我踩过的坑,目前很多博客没有介绍的很清楚:
1.封装文件名需要和代码文件名保持相同
封装时你的Extension("a",["a.py"])第一个"a"是封装后.so文件的名字,由于我不想透露这个名字,我在写的时候改成了c,比如Extension("c",["a.py"]),这是生成的so文件会是c.so,但是如果b.py调用了a.py,那么就会报错,它不认识c.so文件。
2.如果代码文件有很多子目录怎么办
如果代码文件目录是:
--root:
./a.py
/core/b.py
/core/c.py
其中a调用b c,b c 又互相调用这个问题困扰我很久最后通过一个方法解决了,但我还没有相处原因。
先写一个setup1.py文件并执行:
from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension
extensions = [
Extension("a",["a.py"],include_dirs=["./core"]),
Extension("b",["core/b.py"],include_dirs=["../core"]),
Extension("c",["core/c.py"], include_dirs=["../core"]),
]
setup(ext_modules=cythonize(extensions))
先执行完这个文件(python3 setup.py build_ext)再执行下面的
from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension
extensions = [
Extension("a",["a.py"],include_dirs=["./core"]),
Extension("core/b",["core/b.py"],include_dirs=["../core"]),
Extension("core/c",["core/c.py"], include_dirs=["../core"]),
]
setup(ext_modules=cythonize(extensions))
只执行其中一个都会报错,我现在还不明白原因,但是依次执行生成的lib*文件夹就没有问题。
后面的操作相同的。
至于增加了inlude_dirs = ["./core"]我尚不清楚是否有用,但我实际执行的代码里写了
3.中间生成的temp*文件夹
我发现封装过程中build文件夹下的temp*文件夹是没用的,cd进去以后也不能用,最终的封装结果也不需要这个文件夹。