安装时复制配置文件

Copy configuration file on installation

我正在尝试打包我的 Python 项目,它带有一个配置点文件,我想在安装时将其复制到用户的主目录中。打包快速指南说这可以使用 setuptools.setupdata_files 参数来完成。这就是我所拥有的:

data_files = [(os.path.expanduser("~"), [".my_config"])]

如果我使用 python setup.py install,这似乎工作正常,但是当我将我的包上传到 PyPI 并且 运行 pip install 点文件没有被复制。

FWIW,我已将点文件放在 MANIFEST.in 中,还尝试将 package_data 参数包含在 setup 中。 None 这些步骤似乎有所作为。如果我 pip install 并浏览 site-packages 目录,这里只有源文件。

我怎样才能实现我正在寻找的东西?

这是我亲身经历过的一个问题。其根源在于,当你构建wheel文件时,data_files中指定的所有绝对路径都会相对化到目标site-packages目录中,参见this issue on github。这会影响 pip install 执行的安装,因为它将使用任何源包(.tar.gz.tar.bz2.zip)构建一个轮子并安装生成的轮子:

$ pip install spam-0.1.tar.gz
正在处理 ./spam-0.1.tar.gz
<b>为收集的包裹造轮子:垃圾邮件
  运行 setup.py bdist_wheel 垃圾邮件...完成</b>
  存储在目录中:/Users/hoefling/Library/Caches/pip/wheels/d0/95/be/bc79f1d589d90d67139481a3e706bcc54578fdbf891aef75c0
成功构建垃圾邮件
安装收集的包:垃圾邮件
成功安装spam-0.1

检查安装的文件产生:

$ pip show -f spam
名称:垃圾邮件
版本:0.1
...
位置:/Users/hoefling/.virtualenvs/Whosebug/lib/python3.6/site-packages
要求:
档案:
  <b>Users/hoefling/.my_config</b>
  spam-0.1.dist-info/DESCRIPTION.rst
  垃圾邮件-0.1.dist-info/INSTALLER
  垃圾邮件-0.1.dist-info/METADATA
  垃圾邮件-0.1.dist-info/RECORD
  垃圾邮件-0.1.dist-info/WHEEL
  spam-0.1.dist-info/metadata.json
  spam-0.1.dist-info/top_level.txt

请注意,绝对路径是相对于 Location 目录的。在示例中,.my_config 将放置在 /Users/hoefling/.virtualenvs/Whosebug/lib/python3.6/site-packages/Users/hoefling/.my_config.

它变得更好,因为这些内置轮子缓存在您的磁盘上,所以下次您重新安装软件包并且内置轮子仍然存在于 pip 的缓存中时,它将用于安装和您甚至不会在终端日志中看到任何关于构建轮子的提及。

没有真正的解决方案可以避免这种情况。我发现最合适的解决方法是在安装时禁止 "binary" 包,以强制执行包的 setup.py 安装:

$ pip install spam-0.1.tar.gz --no-binary=spam
Processing ./spam-0.1.tar.gz
Skipping bdist_wheel for spam, due to binaries being disabled for it.
Installing collected packages: spam
  Running setup.py install for spam ... done
Successfully installed spam-0.1

文件现已正确放置:

$ pip show -f spam
Name: spam
Version: 0.1
...
Location: /Users/hoefling/.virtualenvs/Whosebug/lib/python3.6/site-packages
Requires: 
Files:
  ../../../../../.my_config
  spam-0.1-py3.6.egg-info/PKG-INFO
  spam-0.1-py3.6.egg-info/SOURCES.txt
  spam-0.1-py3.6.egg-info/dependency_links.txt
  spam-0.1-py3.6.egg-info/top_level.txt

不幸的是,必须单独通知用户调用 pip install 使用额外的密钥(通过自述文件、网页常见问题解答或类似的方式),因为不可能禁止在包元数据中构建轮子。

因此,我不再包含具有绝对路径的文件。相反,我将它们与 site-packages 目录中的 python 源一起安装。在 python 代码中,如果需要,我必须为存在性检查和文件复制添加额外的逻辑:

# program entrypoint

if __name__ == '__main__':
    config = os.path.join(os.path.expanduser('~'), '.my_config')
    if not os.path.exists(config):
        shutil.copyfile('.my_config', config)
    main.run()

除了@hoefling 所说的,我建议你完全不要使用 data_files!因为真的无法预测文件将被复制到哪里。您可以通过为目录提供 '''/''/anything/you/want'.

之类的内容来对此进行测试

我建议你改用package_data,它只会在安装时复制分发包根目录下的文件。然后您可以在 运行 时间将其复制到您想要的任何位置。

有关 package_data 的更多信息,请参阅 Python 文档 https://docs.python.org/2/distutils/setupscript.html#installing-package-data