pip install在编写installed-files.txt时错过了一些生成的文件

时间:2014-09-05 13:21:44

标签: python python-2.7 pip

pip install具有自定义build_py命令的项目在构建目录中生成其他文件时,由pip在安装上生成的installed-files.txt文件不会列出生成的文件。因此,当我卸载发行版时,它会留下我生成的文件。

我想我无法以某种方式注册生成的文件,但我找不到任何关于如何执行此操作的文档。

我必须更改哪些内容,以便pip的installed-files.txt列出我生成的文件?

复制步骤

创建以下文件系统条目。

installed-files-missing-project
├── install-entry-missing
│   └── __init__.py
└── setup.py

将以下内容放入setup.py。

import os

from setuptools import setup
from setuptools.command.build_py import build_py


def touch(fname, times=None):
    with open(fname, 'a'):
        os.utime(fname, times)


class my_build_py(build_py):
    def run(self):
        if not self.dry_run:
            target_dir = os.path.join(self.build_lib, "install-entry-missing")
            self.mkpath(target_dir)
            touch(os.path.join(target_dir, "my_file.txt"))
            # TODO: missing registration of "my_file.txt"?
        build_py.run(self)


setup_args = dict(
    name='install-entry-missing',
    version='1.0.0',
    description='',
    author='author',
    author_email='author@example.com',
    packages = ["install-entry-missing"],
    cmdclass={'build_py': my_build_py}
)


if __name__ == '__main__':
    setup(**setup_args)

install-entry-missing-project目录中,运行pip install .

安装的目录将包含my_file.txt和__init__.py。但是,检查egg-info目录的installed-files.txt将显示未列出my_file.txt。因此,pip uninstall install-entry-missing将删除__init__.py但不会删除my_file.txt。

3 个答案:

答案 0 :(得分:2)

通过覆盖get_outputs的{​​{1}}方法而非使用build_py,可以获得比Eric's answer中建议的更清晰的代码:

install_egg_info

虽然Eric's answer中使用的方法有效,但为了更新 installed-files.txt ,覆盖import os from setuptools import setup from setuptools.command.build_py import build_py def touch(fname, times=None): with open(fname, 'a'): os.utime(fname, times) class my_build_py(build_py): def run(self): self.my_outputs = [] if not self.dry_run: target_dir = os.path.join(self.build_lib, "install-entry-missing") self.mkpath(target_dir) output = os.path.join(target_dir, "my_file.txt") touch(output) self.my_outputs.append(output) build_py.run(self) def get_outputs(self): outputs = build_py.get_outputs(self) outputs.extend(self.my_outputs) return outputs setup_args = dict( name='install-entry-missing', version='1.0.0', description='', author='author', author_email='author@example.com', packages = ["install-entry-missing"], cmdclass={'build_py': my_build_py} ) if __name__ == '__main__': setup(**setup_args) 在语义上可疑,因为您正在更新相关文件列表到 egg-info 目录中安装的内容。在install_egg_info中覆盖get_outputs可以使更改的文件列表更接近于生成它们的位置,并且可以更轻松地处理生成的文件仅在运行时确定的情况。

答案 1 :(得分:1)

必须覆盖install_egg_info命令并在其self.outputs列表中附加一个条目。 self.outputs列表中的每个条目都将在最终的installed-files.txt中生成一个条目。

修改上面的代码,正确的解决方案是:

import os

from setuptools import setup
from setuptools.command.build_py import build_py
from setuptools.command.install_egg_info import install_egg_info


def touch(fname, times=None):
    with open(fname, 'a'):
        os.utime(fname, times)


class my_build_py(build_py):
    def run(self):
        if not self.dry_run:
            target_dir = os.path.join(self.build_lib, "install-entry-missing")
            self.mkpath(target_dir)
            touch(os.path.join(target_dir, "my_file.txt"))
            # this file will be registered in my_install_egg_info
        build_py.run(self)


class my_install_egg_info(install_egg_info):
    def run(self):
        install_egg_info.run(self)
        target_path = os.path.join(self.install_dir, "my_file.txt")
        self.outputs.append(target_path)


setup_args = dict(
    name='install-entry-missing',
    version='1.0.0',
    description='',
    author='author',
    author_email='author@example.com',
    packages = ["install-entry-missing"],
    cmdclass={'build_py': my_build_py,
              'install_egg_info': my_install_egg_info}
)


if __name__ == '__main__':
    setup(**setup_args)

答案 2 :(得分:0)

我遇到的问题与此帖所描述的类似。上述解决方案无效。我创建了一个符号链接作为我的setup.py。

的安装后步骤

我按照pip源代码中的代码来查看installed-files.txt的内容,看看发生了什么。事实证明,由于我的文件是一个符号链接,它被忽略了。在pip / req / req_uninstall.py的第50行,对normalise_path的调用遵循符号链接,只是将链接文件添加到要删除的路径列表中。链接本身不会添加到要删除的文件列表中,因此会被丢弃并由安装程序保留。

作为一项解决方法,我将符号链接更改为硬链接,然后pip完全卸载了我的包。