PyPI 包名的命名规则与 pip 的兼容性机制——为什么 pip install sCIKit.-_LEarN 也能成功

前言

最近我在使用 pip install 命令安装包时,偶然发现在包名中使用下划线和使用连字符都可以成功安装,而且安装的确实是同一个包。这就激发了我的好奇心,难道 pip install 命令中下划线和连字符是等效的?于是我就去网上搜索了一下,并整理了相关资料写成这篇博文。

PyPI 包名规则

PyPA 编写的 Python 软件打包用户指南 中说明,包名允许包含大小写字符、数字、句点、连字符、下划线这几种符号。但同时制定了一个规则,叫包名规范化。包名规范化主要包含三个规则:

  1. 规范包名中的大写字母会全部转换为小写字母
  2. 规范包名中句点(.)连字符(-)下划线(_)会被统一转换为连字符
  3. 如果存在多个连字符,会转换为 1 个

因此,实际上以下几种包名是等价的:

  • friendly-bard
  • Friendly-Bard
  • FRIENDLY-BARD
  • friendly.bard
  • friendly_bard
  • friendly--bard
  • FrIeNdLy-._.-bArD (尽管很糟糕,但它确实有效)

最终都会转换为规范形式的包名:friendly-bard

pip 安装和卸载包的处理方式

在使用 pip install <包名> 命令安装包时,pip 会首先将包名转换为规范包名,之后再去 Pypi 库查找并安装。因此,假设你要安装 scikit-learn 这个包,你甚至可以执行 pip install sCIKit.-_LEarN,也是可以安装成功的。

同样的,在卸载包时,pip uninstall <包名> 命令也一样,大写字符会自动转成小写,其他的连接符会自动转换为连字符。

打印日志细节的不同

不过我发现 pip installpip uninstall 在命令执行成功后的打印日志上细节还是有些不同。以用户输入的包名为 sCIKit.-_LEarN 为例,pip install sCIKit.-_LEarN 执行成功后,输出的是:

Successfully installed joblib-1.5.2 sCIKit.-_LEarN-1.6.1 threadpoolctl-3.6.0

可以看到其中输出的包名和用户输入的一致。

pip uninstall sCIKit.-_LEarN 执行成功后,输出的是:

Successfully uninstalled scikit-learn-1.6.1

可以看到其中输出的包名是规范包名。

目前并不清楚 pip 在安装和卸载时显示的包名有两种行为模式的原因,可能是有意为之。

番外篇:包名和模块名的不同

需要注意的是,pip install 的包名和在 python 代码中使用 import 导入的相关模块名称并不一定完全一致。

比如常用的机器学习包 sklearn,在代码中导入的用法为:from sklearn import *,但安装的命令却是 pip install scikit-learn,而不是 pip install sklearn。这也是很多新手会踩的一个坑。

  • pip
    5 引用 • 1 回帖
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    561 引用 • 677 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...