Arch-Linux

pip freeze 列出通過 pip 解除安裝,然後通過 Pacman 重新安裝的軟體包

  • May 29, 2018

因為我聽說通過pip而不是通過包管理器安裝包是一個非常糟糕的主意,所以我試圖確定我通過pip它安裝的所有包,這些包也可以在pacman’s 的官方儲存庫中輕鬆獲得。並不是所有的都是(我知道我可以自己探索 AUR 或打包它們,但現在我正試圖留在官方儲存庫中),所以我暫時保留其中一些安裝pip,並遷移休息到pacman

我的(誠然原始的)工作流程是:

  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列出了看起來正確的文件,而且有趣的是,我也看到包更新過pacman,這表明它pacman已經接管了更新包的責任。

但是,問題在於它pip freeze仍然列出了這些包,即使它們已經通過pip.

例如,兩者pip freeze | grep pylint和都pacman -Qqe | grep pylint表示軟體包已安裝。我可以通過其中一個sudo pacman -Rs python-pylint或通過sudo pip uninstall pylint.

如果我這樣做 -通過pip或通過pacmanpip freeze解除安裝包 - 包將從列表中消失,並且pacman -Qqe不再找到任何東西。如果我通過 重新安裝包pacman -S,則包會重新出現在pip freeze. 通過重新安裝包pip不會提示它重新出現在pacman -Qqe.

pip通過執行解除安裝軟體包sudo pip uninstall packagename,然後使用--user標誌 (ie pip install --user packagename) 重新安裝它會導致sudo pip freeze不顯示該軟體包,而是pip freeze繼續顯示它。通過重新安裝包pacman會導致它重新出現在兩個列表中。


我不認為這個問題與此連結上的問題重複;在那個問題中,使用者無法pip freeze通過解除安裝軟體包來刪除它們,並且該問題被跟踪到多個不同的pip二進製文件。

在這種情況下,通過解除安裝軟體包pip確實會將其從 中刪除pip freezewhich pip並且sudo 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,哪些是通過pip和安裝的pacman
  • 可以做些什麼來糾正更廣泛的問題:pip跟踪通過安裝的包pacman

我編寫了一個 python 腳本(gist 連結)來檢查所有 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出現。

引用自:https://unix.stackexchange.com/questions/444195