pip freeze 列出通过 pip 卸载然后通过 Pacman 重新安装的软件包

pip freeze 列出通过 pip 卸载然后通过 Pacman 重新安装的软件包

因为我听说通过pip而不是通过包管理器安装包是一个非常糟糕的主意,所以我试图找出我通过 安装了的所有包,pip这些包在 的官方存储库中也很容易找到。并非所有的包都是如此(我知道我可以探索 AUR 或自己打包它们,但目前我试图留在官方存储库中),所以我暂时pacman保留其中一些安装,并将其余的迁移到。pippacman

我(诚然是原始的)执行此操作的工作流程是:

  1. pip freeze | less;选择要迁移的包(基本上是任意的)
  2. pacman -Ss python-packagename(如果未找到,则中止并使用不同的包重试)
  3. sudo pip uninstall packagename
  4. sudo pacman -S python-packagename
  5. 如果pacman报告文件冲突,请对所有依赖包重复步骤 2 到 4,然后在目标包上重新尝试步骤 5。

这是有效的,因为我相信我现在已经成功地通过pacman-列出了显示正确的文件来管理包,并且有趣的是,我也pacman -Ql python-packagename看到了包的更新,这表明它已经接管了更新包的责任。pacmanpacman

但问题是,pip freeze仍然列出了这些软件包,即使它们已通过pip.

例如, 和pip freeze | grep pylintpacman -Qqe | grep pylint表示该软件包已安装。我可以通过sudo pacman -Rs python-pylint或 通过成功卸载该软件包sudo pip uninstall pylint

如果我这样做 - 卸载该软件包要么通过pip要么通过pacman- 包裹从pip freeze的列表中消失,并且pacman -Qqe不再找到任何东西。如果我随后通过 重新安装该软件包pacman -S,该软件包将重新出现在 中pip freeze。通过重新安装包pip不会提示它重新出现在pacman -Qqe.

pip通过运行卸载软件包sudo pip uninstall packagename,然后使用--user标志(即pip install --user packagename)重新安装它,会导致sudo pip freeze不显示该软件包,但pip freeze继续显示它。重新安装该软件包pacman会使其重新出现在两个列表中。


我不认为这个问题与上一个问题重复在这个链接;在该问题中,用户无法pip freeze通过卸载来删除软件包,并且问题被追踪到多个不同的pip二进制文件。

在这种情况下,通过卸载软件包pip确实会将其从 中删除pip freeze,并且which pipsudo which pip具有相同的输出:/usr/bin/pip。此外,sudo pip freezepip freeze产生相同的输出。

然而,对上面链接的问题的接受答案提出的测试表现出我认为奇怪的行为。 (在运行以下测试时,pylint已通过 卸载pip并重新安装pacman。)

$ python -c 'import pkg_name' &> /dev/null && echo installed || echo not installed
Using config file /home/[my user name]/.pylintrc
not installed

该软件包确实已安装 - 它不仅打印配置文件行,而且我可以正常使用该软件包(pylint foo.py)。难道我不希望打印测试吗installed


为了回答我关于这个问题的实际问题:

  • 我可以做什么来确定哪些软件包实际上仅通过 来安装,哪些软件包是通过和pip来“安装”的?pippacman
  • 可以采取什么措施来纠正更广泛的问题:pip跟踪通过安装的软件包pacman

答案1

我写了一个Python脚本(要点链接)检查所有 python 包是否随pacman.

安装

下载脚本并使其可执行:

$ wget https://gist.github.com/hoefling/314565368a66c308b4d7d407a3028cb7/raw/7b81553fa0a84b92a90fbaa0746482d0ec18516c/pip-query -O pip-query
$ chmod +x pip-query

用法

base/archlinux这是一个在我安装的 docker 容器中调用它的示例python-pippython-wheel

$ ./pip-query
Package    Version Owner
---------- ------- -----------------
appdirs    1.4.3   python-appdirs
packaging  17.1    python-packaging
pip        9.0.1   python-pip
pyparsing  2.2.0   python-pyparsing
setuptools 39.2.0  python-setuptools
six        1.11.0  python-six
wheel      0.31.1  python-wheel

输出类似于 的输出pip list --format=columns,但有一个附加列Owner,用于打印拥有 python 包的系统包的名称。

让我们使用直接安装的包进行测试pip

$ sudo pip install tqdm
...
$ ./pip-query
Package    Version Owner
---------- ------- -----------------
appdirs    1.4.3   python-appdirs
packaging  17.1    python-packaging
pip        9.0.1   python-pip
pyparsing  2.2.0   python-pyparsing
setuptools 39.2.0  python-setuptools
six        1.11.0  python-six
tqdm       4.23.4
wheel      0.31.1  python-wheel

Owner列的行中有一个空单元格tqdm,这表明tqdm不是由 安装的pacman。卸载tqdmpip

$ sudo pip uninstall -y tqdm

并安装它pacman

$ pacman -S python-tqdm

永久安装

如果您愿意,请将pip-query文件放置在您的某个地方PATH,最好是本地文件,例如$HOME/.local/bin将其称为正确的可执行文件

$ pip-query

适应其他包管理器

如果您愿意,可以很容易地调整脚本以与其他包管理器一起使用。例如,如果我更改['pacman', '-Qqo', file]['qfile', '-q', file],则脚本将在 Gentoo 上运行,无需任何进一步修改*。如果您的包管理器不支持纯包名称打印,请使用out正则表达式或其他方式从字符串中提取相关信息。

批量重新安装软件包pacman

您可以修改pip-query,或者遵循 Unix 哲学并编写一些 bash 命令来为您重新安装。但是,您必须处理pacman(如下例所示)提出的多个建议,并在没有任何建议的情况下实施该情况。这是我的尝试(不是 bash 专家):

$ ./pip-query | tail -n +3 | while read line ; do split=(${line}); \
> if [ "${#split[@]}" -eq "2" ]; then pkgname=${split[0]}; \
> echo -e "Suggestion: pip uninstall -y $pkgname && pacman -S $(pacman -Sspq $pkgname | tr '\n' ' ')"; \
> fi; done
Suggestion: pip uninstall -y tqdm && pacman -S python-tqdm python2-tqdm

增强这一点,您就拥有了重新安装任务的自动化解决方案。


*:假设app-portage/portage-utils出现。

相关内容