我最近使用命令行将一台计算机从 Ubuntu Server 16.04 LTS 升级到 18.04 LTS。因此,内置Python安装从Python 3.5升级到3.6。而且之前使用
pip3
安装的所有 Python 包似乎都无法再访问。我计划清理所有这些包并使用 conda
进行 Python 包管理。我的问题是,在这种情况下彻底卸载那些无法访问的软件包的最佳实践是什么?
通过
pip3
安装的旧软件包主要位于 /usr/local/lib/python3.5/
和 ~/.local/lib/python3.5/
下。但可能还有其他剩余文件,例如在 /usr/local/bin/
下。我想删除 pip3 install
附带的所有相关文件。
我最终编写了一个 bash 脚本来迭代地调用每个先前安装的包上的
pip3 uninstall
。
#!/bin/bash
pypath_cmd="PYTHONPATH=$HOME/.local/lib/python3.5/site-packages"
export $pypath_cmd
echo "Uninstalling editable packages in $PYTHONPATH"
rm -f $PYTHONPATH/*.egg-link
rm -f $PYTHONPATH/easy-install.pth
pip3 freeze --all --local | cut --delimiter="=" -f 1 | while read pkg ; do
echo $pkg: $(pip3 show $pkg | grep "Location:")
pip3 uninstall -y $pkg
done
pypath_cmd="PYTHONPATH=/usr/local/lib/python3.5/dist-packages"
export $pypath_cmd
echo "Uninstalling editable packages in $PYTHONPATH"
sudo rm -f $PYTHONPATH/*.egg-link
sudo rm -f $PYTHONPATH/easy-install.pth
pip3 freeze --all --local | cut --delimiter="=" -f 1 | while read pkg ; do
echo $pkg: $(pip3 show $pkg | grep "Location:")
sudo $pypath_cmd pip3 uninstall -y --no-cache-dir $pkg
done
sudo pip install
将 pip 软件包安装到 /usr/local/lib/<python_version>/dist-packages
,将 apt 软件包安装到 /usr/lib/<python_version>/dist-packages
。检查这些目录并删除不需要的包。
我最近从 Debian 11 升级到 Debian 12,并忘记在升级前删除旧的 Python (3.9) 软件包。升级后,我被困在Python 3.11中,试图使用之前用Python 3.9安装的用户包,并且我还在旧Pip安装的
~/.local/bin
中安装了一堆可执行文件。 pip3
命令本身指向 ~/.local/bin
。不理想!
我遇到了这个问答,我改进并改编了来自GZ0的脚本。希望它能帮助将来的某个人。在这里:
#!/bin/bash
#
# Marco Bonelli - 2024-04-28
#
# Purge user packages belonging to an old python version that is no longer
# installed after a dist-upgrade. Deleting the entire ~/.local/lib/pythonX.Y
# directory may seem enough, but it really is not as a lot of packages may also
# install executables in ~/.local/bin (and maybe even other additional stuff).
#
# Adapted from: https://stackoverflow.com/a/56960145/3889449
#
# Set this to 'NO' to actually uninstall packages
DRY_RUN='YES'
# Old python version to destroy
VICTIM_VERSION='3.9'
# We will look for site-packages and dist-packages here
VICTIM_LIB_PATH="$HOME/.local/lib/python$VICTIM_VERSION"
log() {
echo -ne '\033[94m'
echo -n "$@"
echo -e '\033[0m'
}
uninstall_kind() {
export PYTHONPATH="$VICTIM_LIB_PATH/$1"
# We ideally whould use the pip of the corresponding python version we are
# uninstalling packages for. Just being cautious here, it may work anyway.
# You can remove this check if you really want.
if ! [[ "$(which pip3)" != *"$VICTIM_LIB_PATH"* ]]; then
echo "WARNING: pip3 does not point into $VICTIM_LIB_PATH" >&2
echo "WARNING: not sure if this could break stuff... aborting!" >&2
exit 1
fi
if [ "$DRY_RUN" = 'NO' ]; then
# --break-system-packages is needed for distros like Debian 12 that set
# their Python installation as "externally managed" to avoid conflicts
# between python packages installed through apt and pip. We are not
# deleting system packages anyway as this script is not run as root, so
# it's safe to use it.
local uninstall_cmd="pip3 uninstall -y --break-system-packages"
else
local uninstall_cmd="log [dry run] pip3 uninstall -y --break-system-packages"
fi
log "Uninstalling packages in $PYTHONPATH"
# List all packages
pip3 freeze --all --local | cut --delimiter="=" -f 1 | while read pkg ; do
# Don't shoot ourselves in the foot by uninstalling pip while using it
if [ "$pkg" = "pip" ]; then
log 'Skipping pip (delete it only at the end)'
continue
fi
# Ask pip to resolve the package
local loc="$(pip3 show $pkg | awk '/Location:/ { print $2 }')"
# If the identified location is within $VICTIM_LIB_PATH then uninstall,
# otherwise skip. This is because we can still very well have listed
# packages under /usr/local/lib and we don't want to remove those (it
# would also fail since we don't have privileges).
if [[ "$loc" == *"$VICTIM_LIB_PATH"* ]]; then
log "Uninstalling $pkg ($loc)"
$uninstall_cmd $pkg
else
log "Skipping $pkg (resolves to $loc)"
fi
done
}
# Abort if run as root, we only want to deal with user packages
if [ "$EUID" -eq 0 ]; then
echo "This script should not be run as root!" >&2
exit 1
fi
for kind in site-packages dist-packages; do
uninstall_kind $kind
done
# Do the last steps manually
echo '----------------------------------------------------------------------'
echo 'Done! You can now safely delete the following:'
echo '- The pip3 command if it points to ~/.local/bin/pip3 (see: which pip3)'
echo "- The directory ~/.local/lib/python$VICTIM_VERSION"