跳转至

AI 编写的实用脚本总结

本文档总结了 AI 编写的 PyPI Server 相关实用脚本


一、多平台多版本包下载脚本

1.1 脚本功能

  • 一键下载指定 Python 包及其所有依赖
  • 支持多个 Python 版本(默认:3.11.5, 3.12.4, 3.13.2)
  • 自动为 Windows 和 Linux 平台下载对应版本的包
  • 支持命令行参数或 requirements.txt 文件
  • 提供详细的下载统计信息

1.2 脚本代码

#!/bin/bash

# 多平台多版本 Python 包下载脚本
# 用法: ./download-packages.sh <包名> [包名2] [包名3] ...
#       ./download-packages.sh -r <requirements.txt>
#       ./download-packages.sh -v <python版本> <包名>...

set -e

# 默认Python版本列表(可扩展)
PYTHON_VERSIONS=("3.11.5" "3.12.4" "3.13.2")

# 配置
PACKAGES_DIR="/app/pypi-server/packages"

# 创建目录
echo "创建目录结构..."
mkdir -p "${PACKAGES_DIR}"

# 显示帮助信息
show_help() {
    echo "用法: $0 [选项] <包名> [包名2] [包名3] ..."
    echo "      $0 [选项] -r <requirements.txt>"
    echo ""
    echo "选项:"
    echo "  -v, --versions <版本1,版本2,...>  指定Python版本列表(逗号分隔)"
    echo "                                        例如: -v 3.11.5,3.12.4"
    echo "  -r, --requirement <文件>           从requirements.txt读取包列表"
    echo "  -h, --help                         显示帮助信息"
    echo ""
    echo "示例:"
    echo "  $0 flask django requests"
    echo "  $0 -r requirements.txt"
    echo "  $0 -v 3.11.5,3.12.4 lxml"
    echo ""
    echo "当前支持的Python版本: ${PYTHON_VERSIONS[*]}"
    echo "下载目录: ${PACKAGES_DIR}"
}

# 解析命令行参数
PACKAGES=""
REQUIREMENTS_FILE=""

while [[ $# -gt 0 ]]; do
    case $1 in
        -h|--help)
            show_help
            exit 0
            ;;
        -v|--versions)
            IFS=',' read -ra PYTHON_VERSIONS <<< "$2"
            shift 2
            ;;
        -r|--requirement)
            REQUIREMENTS_FILE="$2"
            shift 2
            ;;
        -*)
            echo "错误: 未知选项 $1"
            echo "使用 -h 或 --help 查看帮助"
            exit 1
            ;;
        *)
            PACKAGES="$PACKAGES $1"
            shift
            ;;
    esac
done

# 检查参数
if [ -z "$PACKAGES" ] && [ -z "$REQUIREMENTS_FILE" ]; then
    echo "错误: 未指定包名或requirements文件"
    echo "使用 -h 或 --help 查看帮助"
    exit 1
fi

# 处理 requirements.txt 文件
if [ -n "$REQUIREMENTS_FILE" ]; then
    if [ ! -f "$REQUIREMENTS_FILE" ]; then
        echo "错误: 文件 $REQUIREMENTS_FILE 不存在"
        exit 1
    fi

    echo "从文件读取包列表: $REQUIREMENTS_FILE"

    # 读取 requirements.txt 并提取包名(跳过注释和空行,只保留包名部分)
    PACKAGES=$(grep -v '^#' "$REQUIREMENTS_FILE" | grep -v '^$' | awk -F'==|>=|<=|>|<|~=' '{print $1}' | tr '\n' ' ')

    if [ -z "$PACKAGES" ]; then
        echo "错误: 文件 $REQUIREMENTS_FILE 中没有找到有效的包"
        exit 1
    fi

    echo "将要下载的包: $PACKAGES"
fi

echo "========================================="
echo "开始下载包: ${PACKAGES}"
echo "========================================="
echo "支持的Python版本: ${PYTHON_VERSIONS[*]}"
echo "下载目录: ${PACKAGES_DIR}"
echo "========================================="

# 统计初始包数量
INITIAL_COUNT=$(ls -1 ${PACKAGES_DIR}/*.whl 2>/dev/null | wc -l)

# 函数:下载指定Python版本和平台的包
download_packages() {
    local python_version=$1
    local platform=$2
    local description=$3

    echo ""
    echo ">>> Python ${python_version} - ${description}..."

    local cmd="pip download -d ${PACKAGES_DIR} --only-binary=:all: ${PACKAGES} --python-version=${python_version}"

    if [ -n "$platform" ]; then
        cmd="$cmd --platform=${platform}"
    fi

    $cmd || true
}

# 为每个Python版本下载所有平台的包
for py_version in "${PYTHON_VERSIONS[@]}"; do
    echo ""
    echo "========================================="
    echo "处理 Python ${py_version}..."
    echo "========================================="

    # 1. 下载共享包(py3-none-any,所有Python版本和平台兼容)
    download_packages "${py_version}" "" "共享包 (所有平台兼容)"

    # 2. 下载 Windows 平台包
    download_packages "${py_version}" "win_amd64" "Windows x86_64"

    # 3. 下载 Linux 平台包(manylinux2014)
    download_packages "${py_version}" "manylinux2014_x86_64" "Linux x86_64 (manylinux2014)"

    # 4. 下载 Linux 平台包(manylinux_2_17)
    download_packages "${py_version}" "manylinux_2_17_x86_64" "Linux x86_64 (manylinux_2_17)"
done

echo ""
echo "========================================="
echo "下载完成!"
echo "========================================="
echo "下载目录: ${PACKAGES_DIR}"
echo ""
echo "统计信息:"
FINAL_COUNT=$(ls -1 ${PACKAGES_DIR}/*.whl 2>/dev/null | wc -l)
NEW_COUNT=$((FINAL_COUNT - INITIAL_COUNT))
echo "  - 下载前包数量: ${INITIAL_COUNT}"
echo "  - 新下载包数量: ${NEW_COUNT}"
echo "  - 总包数量: ${FINAL_COUNT}"
echo ""
echo "各Python版本包统计:"
for py_version in "${PYTHON_VERSIONS[@]}"; do
    count=$(ls -1 ${PACKAGES_DIR}/*cp${py_version//./}*.whl 2>/dev/null | wc -l)
    echo "  - Python ${py_version}: ${count} 个包"
done
echo ""
echo "各平台包统计:"
win_count=$(ls -1 ${PACKAGES_DIR}/*win_amd64*.whl 2>/dev/null | wc -l)
linux_count=$(ls -1 ${PACKAGES_DIR}/*manylinux*.whl 2>/dev/null | wc -l)
shared_count=$(ls -1 ${PACKAGES_DIR}/*none-any*.whl 2>/dev/null | wc -l)
echo "  - Windows 平台: ${win_count} 个包"
echo "  - Linux 平台: ${linux_count} 个包"
echo "  - 通用包 (any): ${shared_count} 个包"
echo "========================================="

1.3 使用方法

下载单个包

bash download-packages.sh flask

下载多个包

bash download-packages.sh flask django requests

使用 requirements.txt

bash download-packages.sh -r requirements.txt

指定 Python 版本

bash download-packages.sh -v 3.11.5,3.12.4 lxml

二、单平台版本下载脚本(简化版)

2.1 脚本功能

  • 固定 Python 版本 3.11.5
  • 分类存储(windows/linux/shared 目录)
  • 自动合并到主目录
  • 支持 requirements.txt 文件

2.2 脚本代码

#!/bin/bash

# 多平台 Python 包下载脚本
# 用法: ./download-packages.sh <包名> [包名2] [包名3] ...
# 或者 bash download-packages.sh -r requirements.txt
set -e

# 检查参数
if [ $# -eq 0 ]; then
    echo "用法: $0 <包名> [包名2] [包名3] ..."
    echo "      $0 -r <requirements.txt>"
    echo ""
    echo "示例:"
    echo "  $0 flask django requests"
    echo "  $0 -r requirements.txt"
    exit 1
fi

# 配置
PYTHON_VERSION="3.11.5"
PACKAGES_DIR="/app/pypi-server/packages"
WINDOWS_DIR="${PACKAGES_DIR}/windows"
LINUX_DIR="${PACKAGES_DIR}/linux"
SHARED_DIR="${PACKAGES_DIR}/shared"

# 创建目录
echo "创建目录结构..."
mkdir -p "${WINDOWS_DIR}"
mkdir -p "${LINUX_DIR}"
mkdir -p "${SHARED_DIR}"

# 处理 requirements.txt 文件
if [ "$1" == "-r" ] || [ "$1" == "--requirement" ]; then
    REQUIREMENTS_FILE="$2"

    if [ -z "$REQUIREMENTS_FILE" ]; then
        echo "错误: 未指定 requirements.txt 文件"
        echo "用法: $0 -r <requirements.txt>"
        exit 1
    fi

    if [ ! -f "$REQUIREMENTS_FILE" ]; then
        echo "错误: 文件 $REQUIREMENTS_FILE 不存在"
        exit 1
    fi

    echo "从文件读取包列表: $REQUIREMENTS_FILE"

    # 读取 requirements.txt 并提取包名
    PACKAGES=$(grep -v '^#' "$REQUIREMENTS_FILE" | grep -v '^$' | awk -F'==|>=|<=|>|<|~=' '{print $1}' | tr '\n' ' ')

    if [ -z "$PACKAGES" ]; then
        echo "错误: 文件 $REQUIREMENTS_FILE 中没有找到有效的包"
        exit 1
    fi

    echo "将要下载的包: $PACKAGES"
else
    # 直接使用命令行参数
    PACKAGES="$@"
fi

echo "========================================="
echo "开始下载包: ${PACKAGES}"
echo "========================================="

# 函数:下载共享包(py3-none-any)
download_shared() {
    echo ""
    echo ">>> 下载共享包 (所有平台兼容)..."
    pip download -d "${SHARED_DIR}" --only-binary=:all: ${PACKAGES} --python-version=${PYTHON_VERSION} || true
}

# 函数:下载 Windows 平台包
download_windows() {
    echo ""
    echo ">>> 下载 Windows 平台包..."
    pip download -d "${WINDOWS_DIR}" --only-binary=:all: ${PACKAGES} --python-version=${PYTHON_VERSION} --platform=win_amd64 || true
}

# 函数:下载 Linux 平台包
download_linux() {
    echo ""
    echo ">>> 下载 Linux 平台包..."
    pip download -d "${LINUX_DIR}" --only-binary=:all: ${PACKAGES} --python-version=${PYTHON_VERSION} --platform=manylinux2014_x86_64 || true
}

# 执行下载
download_shared
download_windows
download_linux

echo ""
echo "========================================="
echo "下载完成!"
echo "========================================="
echo "包存储位置:"
echo "  - 共享包 (py3-none-any): ${SHARED_DIR}"
echo "  - Windows 平台包: ${WINDOWS_DIR}"
echo "  - Linux 平台包: ${LINUX_DIR}"
echo ""
echo "统计信息:"
echo "  - 共享包数量: $(ls -1 ${SHARED_DIR}/*.whl 2>/dev/null | wc -l)"
echo "  - Windows 包数量: $(ls -1 ${WINDOWS_DIR}/*.whl 2>/dev/null | wc -l)"
echo "  - Linux 包数量: $(ls -1 ${LINUX_DIR}/*.whl 2>/dev/null | wc -l)"
echo ""
echo "合并所有包到主目录..."
cp -f ${SHARED_DIR}/*.whl ${PACKAGES_DIR}/ 2>/dev/null || true
cp -f ${WINDOWS_DIR}/*.whl ${PACKAGES_DIR}/ 2>/dev/null || true
cp -f ${LINUX_DIR}/*.whl ${PACKAGES_DIR}/ 2>/dev/null || true

echo "总包数量: $(ls -1 ${PACKAGES_DIR}/*.whl 2>/dev/null | wc -l)"
echo "========================================="

2.3 使用方法

# 下载单个包
bash download-packages-v1.sh flask

# 下载多个包
bash download-packages-v1.sh flask django requests

# 使用 requirements.txt
bash download-packages-v1.sh -r requirements.txt

三、脚本对比

特性 多版本脚本 单版本脚本
Python 版本 多版本(3.11.5, 3.12.4, 3.13.2) 单版本(3.11.5)
平台支持 Windows + Linux (2种规格) Windows + Linux (1种规格)
分类存储 否,直接存储到主目录 是(windows/linux/shared)
自定义版本 支持 -v 参数 需修改脚本代码
适用场景 多版本 Python 环境 单一 Python 版本环境

四、部署说明

4.1 上传脚本到服务器

# 将脚本上传到服务器
scp download-packages.sh root@192.168.222.5:/app/pypi-server/

# SSH 登录服务器
ssh root@192.168.222.5

4.2 赋予执行权限

chmod +x /app/pypi-server/download-packages.sh

4.3 激活 conda 环境

source ~/anaconda3/etc/profile.d/conda.sh
conda activate pypi-server

五、输出示例

=========================================
开始下载包: flask
=========================================
支持的Python版本: 3.11.5 3.12.4 3.13.2
下载目录: /app/pypi-server/packages
=========================================

=========================================
处理 Python 3.11.5...
=========================================

>>> Python 3.11.5 - 共享包 (所有平台兼容)...
Collecting flask
  Using cached flask-3.1.2-py3-none-any.whl.metadata (3.2 kB)
...
Successfully downloaded flask blinker click itsdangerous jinja2 markupsafe werkzeug

>>> Python 3.11.5 - Windows x86_64...
...

>>> Python 3.11.5 - Linux x86_64 (manylinux2014)...
...

=========================================
下载完成!
=========================================
下载目录: /app/pypi-server/packages

统计信息:
  - 下载前包数量: 0
  - 新下载包数量: 25
  - 总包数量: 25

各Python版本包统计:
  - Python 3.11.5: 8 个包
  - Python 3.12.4: 8 个包
  - Python 3.13.2: 9 个包

各平台包统计:
  - Windows 平台: 8 个包
  - Linux 平台: 8 个包
  - 通用包 (any): 9 个包
=========================================

六、注意事项

  1. 磁盘空间:下载多平台包会占用更多磁盘空间
  2. 网络带宽:需要下载多个平台的包,建议在网络稳定时执行
  3. Python 版本:确保 PYTHON_VERSION 配置与目标环境一致
  4. 依赖冲突:如果某些包有复杂的依赖关系,可能需要额外处理
  5. 错误处理:脚本使用 || true 确保单个平台下载失败不影响其他平台