我在Python扩展中使用了仅 header 的C++库。我希望能够将它们安装到Python的include路径,以便可以使用python3 setup.py build
轻松编译扩展。我的能力有限,但是有两件事我无法工作(请参见下文):
python3 setup.py install
安装头文件?目前,我只得到一些*.egg
文件,但没有安装头文件。 什么有效
使用以下
setup.py
from setuptools import setup
setup(
name = 'so',
description = 'Example',
headers = [
'so.h',
],
)
我可以将模块上传到PyPi:
python3 setup.py bdist_wheel --universal
twine upload dist/*
然后使用pip安装它:
pip3 install so
在我的系统上,然后我在这里找到标题
/usr/local/include/python3.6m/so/so.h
当我使用Python编译扩展时可用。
如何使用“python3 setup.py install”?
使用这种策略,我不能简单地运行
python3 setup.py install
在这种情况下,将安装一些
so*.egg
,但 header 不会存储在编译器可用的位置。如何保留文件结构?
当模块稍微复杂一点,并且有一些目录层次结构时,我也会遇到问题。对于以下
setup.py
from setuptools import setup
setup(
name = 'so',
description = 'Example',
headers = [
'so.h',
'so/implementation.h',
],
)
问题是将 header 安装到
/usr/local/include/python3.6m/so/so.h
/usr/local/include/python3.6m/so/implementation.h
从而使原始文件结构扁平化。
如何解决这两个问题?
最佳答案
不幸的是,只要您使用setuptools
,您就不能这样做。调用setuptools.setup()
会在后台发生什么?一个egg安装程序正在构建(bdist_egg
命令)并安装(通过easy_install
),并且bdist_egg
和easy_install
都不支持包含/安装头文件。尽管distribution
对象带有 header 信息,但在install
命令期间从未请求过它。这是一个老的众所周知的问题,但从未解决,因为显然,头文件的安装不适合egg build/install过程。
因此,您有三个选择(或者至少我知道三个选择)。不推荐使用它们中的两个(两者都导致切换到distutils
),并且仅出于完整性考虑提供它们:
裸distutils
安装(不推荐)
$ sed 's/from setuptools import setup/from distutils.core import setup/' setup.py
这样,好的
distutils
在执行python setup.py install
时将负责安装,不会构建任何egg安装程序,而是会调用install_headers
。但是,这还包括放弃setuptools
的所有功能,包括setup()
中的其他关键字args和其他所有好东西,不用说,无法通过distutils
卸载通过pip
安装的软件包。old-and-unmanageable
安装(不推荐)使用以下命令运行安装
$ python setup.py install --old-and-unmanageable
如果您明确希望运行
setuptools
安装,这是distutils
提供的开关。不会安装egg安装程序,而是会调用distutils.command.install.install
。因此,安装与裸distutils
安装相同。这种方法的缺点:与裸
distutils
安装相同,外加:setuptools
谴责开关的使用;如果您忘记提供它,则必须先安装鸡蛋,然后重新进行安装。用
python setup.py install
替换pip install
(推荐)pip
能够从源目录安装软件包;只是发出$ pip install dir/
假设
dir
包含setup.py
。这样,就可以从源文件中构建一个wheel文件(与bdist_wheel
中的文件相同;实际上,该命令首先运行)并安装,可以很好地管理头文件的安装。您将需要稍微调整
install_headers
命令:import os
from distutils.command.install_headers import install_headers as install_headers_orig
from setuptools import setup
class install_headers(install_headers_orig):
def run(self):
headers = self.distribution.headers or []
for header in headers:
dst = os.path.join(self.install_dir, os.path.dirname(header))
self.mkpath(dst)
(out, _) = self.copy_file(header, dst)
self.outfiles.append(out)
setup(
name='so',
headers=['h1.h', 'subtree/h2.h'],
cmdclass={'install_headers': install_headers},
...
)
这里必不可少的是生产线
dst = os.path.join(self.install_dir, os.path.dirname(header))
Vanilla
install_headers
copies the header files directly to install_dir
;重载的install_headers
命令中的上述行还负责头文件名中的最终子目录。在安装软件包时,现在应该保留子目录:$ pip show -f so | grep include
../../../include/site/python3.6/so/h1.h
../../../include/site/python3.6/so/subtree/h2.h
关于python - 使用Python安装仅 header 的库,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50101740/