使用pip uninstall 命令可以卸载掉你所安装的第三方库,所有与其相关的文件都将被pip整理出来展示并询问是否真的要删除,类似下面的提示
pip uninstall nox
Found existing installation: nox 2020.8.22
Uninstalling nox-2020.8.22:
Would remove:
d:\python\lib\site-packages\nox-2020.8.22.dist-info\*
d:\python\lib\site-packages\nox\*
d:\python\scripts\nox.exe
d:\python\scripts\tox-to-nox.exe
Proceed (y/n)?
你是否好奇过,pip是如何知道一个库的相关文件所处位置的呢?
pip底层依赖python原生模块pkg_resources,如果你对该模块足够熟悉,很多pip的功能,你自己就可以实现。
第三方模块有多种发行方式,不同的发行方式有自己独特的记录自身模块信息的方法。这里以whl安装文件为例,使用这种文件安装的第三方库会在site-packages里留下一个以dist-info为结尾的文件夹,在这个文件夹里,保留了该模块的许多信息。
这其中有一个名为RECORD的文本文件,里面存储的是这个模块的文件信息,包括文件的地址和sha256值,pip正是从这个文件了解到一个模块有哪些文件。
使用pkg_resources模块,你自己也可以后的这些信息
import pkg_resources
dist = pkg_resources.get_distribution('nox')
for path in dist.get_metadata_lines("RECORD"):
print(path)
get_metadata_lines方法返回的文件目录远远多于卸载时所提示的目录,卸载提示时,只需要提示上层文件夹和个别文件即可,而RECORD记录的是该模块所有的文件,那么pip是如何做到的呢,查看源码,它最终使用一个函数来提取关键的上层目录和文件。
def compact(paths):
# type: (Iterable[str]) -> Set[str]
"""Compact a path set to contain the minimal number of paths
necessary to contain all paths in the set. If /a/path/ and
/a/path/to/a/file.txt are both in the set, leave only the
shorter path."""
sep = os.path.sep
short_paths = set() # type: Set[str]
for path in sorted(paths, key=len):
should_skip = any(
path.startswith(shortpath.rstrip("*")) and
path[len(shortpath.rstrip("*").rstrip(sep))] == sep
for shortpath in short_paths
)
if not should_skip:
short_paths.add(path)
return short_paths
算法非常的巧妙,首先根据目录长度从小到大排序,而后遍历排序后的目录,将上层目录放入到集合short_paths中,后续遍历到的目录如果以某个短目录开头,就说明是这个目录的某个文件,无需放入short_paths中,如此,最终得到的便是上层文件目录和个别的文件地址。
剩下的事情就简单了,执行删除操作就可以了。
QQ交流群: 211426309