You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Python包文件名中准确提取包名与版本号?

从Python包文件名提取包名与版本号的可靠Bash方案

痛点解析

Python包文件名(如whl、tar.gz)的结构看似规律,但包名可能包含数字、下划线/连字符混用,版本号遵循PEP 440规范(支持.dev、.post、rc等后缀),常规的cut/grep/sed分割逻辑很容易在certifi-2024.2.2、charset-normalizer-3.3.2这类案例上出错——要么误把版本号的部分字符当成包名,要么截断版本号。

核心正则逻辑

基于PEP 426的包命名规范,文件名的核心结构为:{包名}-{版本号}-[平台信息].{后缀}。我们可以用正则精准捕获包名和版本号:

  • 包名:由字母、数字、下划线、连字符组成,直到遇到以数字开头的版本号
  • 版本号:以数字开头,包含字母、数字、点、下划线、连字符,覆盖所有PEP 440格式
  • 忽略版本号后的平台信息和后缀

可直接使用的Bash脚本

提取函数

extract_pkg_info() {
    local filename="$1"
    # 正则匹配:捕获包名、版本号,兼容whl/tar.gz/zip后缀
    if [[ "$filename" =~ ^([a-zA-Z0-9_\-]+)-([0-9][0-9a-zA-Z_\.\-]*)(?:-[^.]*)?\.(whl|tar\.gz|zip)$ ]]; then
        local pkg_name="${BASH_REMATCH[1]}"
        local pkg_version="${BASH_REMATCH[2]}"
        # 可选:将下划线转为连字符(部分包文件名用下划线替代标准连字符)
        pkg_name="${pkg_name//_/-}"
        echo "包名: $pkg_name | 版本号: $pkg_version"
    else
        echo "⚠️ 无法解析: $filename"
    fi
}

测试验证

针对之前失败的案例,测试结果如下:

  • 输入:certifi-2024.2.2-py3-none-any.whl → 输出:包名: certifi | 版本号: 2024.2.2
  • 输入:charset-normalizer-3.3.2.tar.gz → 输出:包名: charset-normalizer | 版本号: 3.3.2
  • 输入:charset_normalizer-3.3.2-py3-none-any.whl → 输出:包名: charset-normalizer | 版本号: 3.3.2
  • 输入:scikit-learn-1.4.1.post1-cp310-cp310-manylinux_2_17_x86_64.whl → 输出:包名: scikit-learn | 版本号: 1.4.1.post1
  • 输入:pytest-8.1.0rc1-py3-none-any.whl → 输出:包名: pytest | 版本号: 8.1.0rc1

批量处理目录下的包文件

# 遍历当前目录下所有包文件
for pkg_file in *.whl *.tar.gz *.zip; do
    [[ -f "$pkg_file" ]] && extract_pkg_info "$pkg_file"
done

关键细节说明

  1. 正则非捕获组:(?:-[^.]*)? 用于匹配版本号后的平台信息(如-py3-none-any),但不捕获,避免干扰包名和版本号的提取
  2. 版本号匹配规则:[0-9][0-9a-zA-Z_\.\-]* 确保版本号以数字开头,兼容所有PEP 440允许的格式(包括预发布版本、.post后缀等)
  3. 下划线转连字符:可选步骤,因为部分包的文件名用下划线(如charset_normalizer),但PyPI上的正式包名是连字符,根据需求可删除该逻辑

内容的提问来源于stack exchange,提问作者Stephen Paulin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 22:09:54