我有一個項目取決於共享庫。爲了從頭開始說明:共享庫是一個純粹的C庫,而不是一個Python庫。爲了簡單起見,我創建了一個名爲pkgtest的小型演示項目,我將參考它。如何在Python包中包含共享C庫
所以需要做的是:運行一個Makefile來編譯庫,並將編譯後的共享庫(在此稱爲libhello.so
)文件放置在某個可從取決於的Python包中訪問的位置。
我最好的猜測,到目前爲止是運行makefile作爲一個預安裝程序中,libhello.so
文件複製在包目錄,並將其添加到安裝腳本的package_data
參數。安裝後,共享庫將被置於site-packages/pkgtest/
目錄中,並可通過該模塊進行訪問。
包目錄結構是如此簡單:
pkgtest/
src/
libhello.c
libhello.h
Makefile
pkgtest/
__init__.py
hello.py
setup.py
我setup.py看起來是這樣的:
setup.py
import subprocess
from setuptools import setup
from distutils.command.install import install as _install
class install(_install):
def run(self):
subprocess.call(['make', 'clean', '-C', 'src'])
subprocess.call(['make', '-C', 'src'])
_install.run(self)
setup(
name='pkgtest',
version='0.0.1',
author='stefan',
packages=['pkgtest'],
package_data={'pkgtest': ['libhello.so']},
cmdclass={'install': install},
)
Makefile的實際編制該庫並將其複製到我的python包的目錄中。
的src/Makefile文件
all: libhello.so
libhello.o: libhello.c
gcc -fPIC -Wall -g -c libhello.c
libhello.so: libhello.o
gcc -shared -fPIC -o libhello.so libhello.o
cp libhello.so ../pkgtest/libhello.so
clean:
rm -f *.o *.so
因此,所有hello.py
實際上正在做的是加載庫並調用hello
功能,打印一些文字。但對於完整性,我將在這裏展示的代碼:
pkgtest/hello.py
import os
import ctypes
basedir = os.path.abspath(os.path.dirname(__file__))
libpath = os.path.join(basedir, 'libhello.so')
dll = ctypes.CDLL(libpath)
def say_hello():
dll.hello()
所以這實際上是工作,但我不喜歡這種方式就是共享庫生活在Python包的目錄。我認爲最好將它放在某種中央庫目錄中,例如/usr/lib/。但是,對於這個需要安裝時的root權限。有人有這種問題的一些經驗,並希望分享一個解決方案或有用的想法。會很好。
你有沒有考慮過像[conda](https://conda.io/miniconda.html)這樣的軟件包管理器?您可以爲您的庫和Python代碼創建一個單獨的包,並將該庫指定爲'meta.yaml'文件中Python代碼的依賴關係。 – ostrokach
我沒有想過conda,但。你是對的,這肯定是一個選擇,但不是我的第一選擇,因爲我希望這個軟件包可以通過'pip install ...'來使用。 – MrLeeh
在這種情況下,我不認爲你的python包文件夾中有一個編譯的庫文件是一個問題。這就是[Python擴展模塊](https://docs.python.org/3/extending/building.html)和[Cython](http://docs.cython.org/en/latest/index.html)模塊擺放在。但也許有更好的解決方案... – ostrokach