28

对于使用“setup.py”构建安装包的开发人员来说,这应该是一个非常常见的问题,之前应该问过这个问题,但我在任何地方都找不到正确的答案。

在 setup.py

from distutils.core import setup
setup(
    ....,
    ....,
    data_files=[('MyApp/CBV', ['myapp/data/CBV/training.cbv', 'myapp/data/CBV/test.cbv'])],
    ....,
    ....,
    )

sudo python setup.py install 的结果

running install
running build
running build_py
running build_scripts
running install_lib
running install_scripts
changing mode of /usr/local/bin/MyApp_trainer to 755
changing mode of /usr/local/bin/MyApp_reference_updater to 755
changing mode of /usr/local/bin/MyApp_predictor to 755
changing mode of /usr/local/bin/reference_updater to 755
running install_data
creating /usr/local/MyApp/CBV
copying MyApp/data/CBV/training.cbv -> /usr/local/MyApp/CBV
copying MyApp/data/CBV/test.cbv -> /usr/local/MyApp/CBV
running install_egg_info
Removing /usr/local/lib/python2.7/dist-packages/MyApp-0.1.0.egg-info
Writing /usr/local/lib/python2.7/dist-packages/MyApp-0.1.0.egg-info

使用上面的结果观察,“/usr/local”是“data_files”根目录。除了硬编码之外,是否有任何 Python 函数可以给我这个“data_files”根目录?

4

1 回答 1

19

默认情况下,当以 root 身份安装包时,列表中的相对目录名称将根据(对于纯 Python 库)或(对于具有已编译扩展名的库)data_files的值进行解析,因此您可以根据该值检索文件. 从文档中引用:sys.prefixsys.exec_prefixdistutils

如果directory是相对路径,则相对于安装前缀进行解释(Pythonsys.prefix用于纯 Python 包,sys.exec_prefix用于包含扩展模块的包)。

因此,对于您的示例,您将在os.path.join(sys.prefix, 'MyApp', 'CBV').

但是,最好使用该importlib.resources(Python 3.7 及更高版本)来加载包数据。您确实希望软件包中包含您的数据文件,以使其发挥最佳作用。这意味着您不会使用data_files,而是在 MANIFEST.in 文件和 setinclude_package_data=True中列出文件模式,或者在 中列出文件模式package_data,请参阅在 setuptools 文档中包含数据文件。

对于早期的 Python 版本,您可以使用pkg_resources模块资源 API执行相同的操作来加载数据文件(它是setuptools库的一部分,为此目的)。

然后,您可以直接从包中将此类资源文件加载到字符串中resource_string(),例如:

try:
    from importlib.resources import read_text
except ImportError:
    from pkg_resources import resource_string as read_text

foo_config = read_text(__name__, 'foo.conf')
于 2013-01-08T09:14:34.827 回答