因为我听说通过pip
而不是通过包管理器安装包是一个非常糟糕的主意,所以我试图找出我通过 安装了的所有包,pip
这些包在 的官方存储库中也很容易找到。并非所有的包都是如此(我知道我可以探索 AUR 或自己打包它们,但目前我试图留在官方存储库中),所以我暂时pacman
保留其中一些安装,并将其余的迁移到。pip
pacman
我(诚然是原始的)执行此操作的工作流程是:
pip freeze | less
;选择要迁移的包(基本上是任意的)pacman -Ss python-packagename
(如果未找到,则中止并使用不同的包重试)sudo pip uninstall packagename
sudo pacman -S python-packagename
- 如果
pacman
报告文件冲突,请对所有依赖包重复步骤 2 到 4,然后在目标包上重新尝试步骤 5。
这是有效的,因为我相信我现在已经成功地通过pacman
-列出了显示正确的文件来管理包,并且有趣的是,我也pacman -Ql python-packagename
看到了包的更新,这表明它已经接管了更新包的责任。pacman
pacman
但问题是,pip freeze
仍然列出了这些软件包,即使它们已通过pip
.
例如, 和pip freeze | grep pylint
都pacman -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 pip
和sudo which pip
具有相同的输出:/usr/bin/pip
。此外,sudo pip freeze
和pip 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
来“安装”的?pip
pacman
- 可以采取什么措施来纠正更广泛的问题:
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-pip
:python-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
。卸载tqdm
:pip
$ 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
出现。