setup.py:仅安装 pth 文件?

14 投票
3 回答
2652 浏览
提问于 2025-04-15 18:31

在创建一个自定义的 Python 版本时,最后一步我需要添加一个 myproject.pth 文件。

目前我是在一个 Makefile 里做这件事:

install:
        rm -f            ../../lib/python2.6/site-packages/myproject.pth
        cp myproject.pth ../../lib/python2.6/site-packages/myproject.pth

但我想把这个过程放到一个 setup.py 文件里。可惜的是,setup.py 的文档似乎没有涉及到这个简单的情况!希望能得到一些帮助。我试过这样做,但没有成功:

from setuptools import setup
setup(
    packages=['mypackage_pth'],
    package_dir={'mypackage_pth': '.'},
    package_data={'mypackage_pth': ['mypackage.pth']},
)

3 个回答

0

这段话是从stderr的回答中改编过来的。我不太确定这样做是否合适,但确实有效。

from distutils import sysconfig
site_packages_path = sysconfig.get_python_lib()

import shutil
shutil.copy('mypackage.pth', site_packages_path)

setup(...)
4

你需要找的是 data_files 这个参数,用来设置你的安装包:

from distutils import sysconfig
site_packages_path = sysconfig.get_python_lib()

setup(...,
  data_files=[(site_packages_path, ["mypackage.pth"])]
 )
10

在这里,正确的做法是扩展setuptools的build_py,把源目录中的pth文件复制到构建目录中,也就是setuptools准备放入site-packages的所有文件的位置。

from setuptools.command.build_py import build_py


class build_py_with_pth_file(build_py):
     """Include the .pth file for this project, in the generated wheel."""

     def run(self):
         super().run()

         destination_in_wheel = "mypackage.pth"
         location_in_source_tree = "src/mypackage.pth"
 
         outfile = os.path.join(self.build_lib, destination_in_wheel)
         self.copy_file(location_in_source_tree, outfile, preserve_mode=0)

setup(
   ...,
   cmdclass={"build_py": build_py_with_pth_file},
)

在写这段话的时候,这里其他的答案都有一些微妙的错误。

data_files=[(site_packages_path, ["mypackage.pth"])]

这在语义上是错误的——pth文件不是数据。它是代码,就像你项目中其他的.py文件一样。更重要的是,这在功能上也是有问题的——虽然问题不太明显,但很重要。

这样做会把site_packages_path嵌入到生成的包中。你最终会得到一个包含类似以下文件路径的包:

my_package-1.0.0.data/data/lib/python3.9/site-packages/mypackage.pth

这个包只适用于Python 3.9(因为路径就是这个),但它很容易被标记为py3(也就是说,兼容所有Python版本)。

这很难被发现,因为你需要一个开发流程,能够在多个不同的Python版本上运行测试,使用生成的包。

shutil.copy('mypackage.pth', site_packages_path)

这……不好。

虽然它可以在不同的Python版本上工作,但即使用户只是下载了项目,使用pip download mypackage,这个pth文件也会被“安装”。

更重要的是,为这个项目生成的包不会有任何与项目相关的pth文件。因此,后续的安装不会得到这个pth文件(因为pip会缓存本地构建的包)。

这无法通过在本地从源目录安装来重现,同样也不容易发现:你需要一个开发流程,在与构建环境不同的环境中安装这个包,以便以一种可以检测到的方式运行测试。

撰写回答