|
#!/bin/bash |
|
|
|
# --- Python 源码编译安装脚本 (最终版) --- |
|
# 1. 恢复了“列出已安装版本”的功能。 |
|
# 2. 包含了修复 _sqlite3 等模块缺失问题的依赖。 |
|
# 3. 提供了重新安装功能,并在完成后提示用户修复可能损坏的虚拟环境。 |
|
|
|
# 检查是否提供了版本号参数 |
|
if [ $# -ne 1 ]; then |
|
echo "使用方法: $0 <python版本号>" |
|
echo "示例: $0 3.13.0 或 $0 3.11.4" |
|
exit 1 |
|
fi |
|
|
|
# --- 变量定义 --- |
|
PYTHON_VERSION=$1 |
|
MAJOR_VERSION=$(echo "$PYTHON_VERSION" | cut -d. -f1-2) |
|
INSTALL_PREFIX="/usr/local/python${PYTHON_VERSION}" |
|
PYTHON_BIN="${INSTALL_PREFIX}/bin/python${MAJOR_VERSION}" |
|
PIP_BIN="${INSTALL_PREFIX}/bin/pip${MAJOR_VERSION}" |
|
DOWNLOAD_URL="https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz" |
|
# 自动检测 shell 配置文件 |
|
if [ -n "$ZSH_VERSION" ]; then |
|
RC_FILE="$HOME/.zshrc" |
|
elif [ -n "$BASH_VERSION" ]; then |
|
RC_FILE="$HOME/.bashrc" |
|
else |
|
RC_FILE="$HOME/.profile" |
|
fi |
|
|
|
# --- 环境检查 --- |
|
if ! grep -qE 'ubuntu|debian' /etc/os-release; then |
|
echo "错误: 此脚本仅支持Ubuntu/Debian系统" |
|
exit 1 |
|
fi |
|
|
|
if [ ! -f "$RC_FILE" ]; then |
|
echo "===== 创建 Shell 配置文件: $RC_FILE =====" |
|
touch "$RC_FILE" |
|
fi |
|
|
|
# 列出当前已安装的通过此脚本安装的Python版本 |
|
echo "===== 已安装的Python版本(位于/usr/local/) =====" |
|
installed_versions=$(find /usr/local/ -maxdepth 1 -type d -name "python[0-9.]*" | sort) |
|
if [ -n "$installed_versions" ]; then |
|
while IFS= read -r dir; do |
|
ver=$(basename "$dir" | sed 's/^python//') |
|
echo "- $ver" |
|
done <<< "$installed_versions" |
|
else |
|
echo "未检测到通过本脚本方式安装的Python版本" |
|
fi |
|
|
|
# --- 检查是否已安装并提供重新安装选项 --- |
|
REINSTALL_FLAG=false |
|
if [ -d "${INSTALL_PREFIX}" ]; then |
|
echo -e "\n===== 检测到Python ${PYTHON_VERSION} 的安装目录已存在 =====" |
|
read -p "您想强制重新安装吗?(这将修复问题,但需要您手动重建虚拟环境) [y/N]: " REINSTALL_CHOICE |
|
case "$REINSTALL_CHOICE" in |
|
[yY][eE][sS]|[yY]) |
|
echo "===== 用户选择重新安装,将删除旧目录并继续 =====" |
|
sudo rm -rf "${INSTALL_PREFIX}" |
|
REINSTALL_FLAG=true |
|
;; |
|
*) |
|
echo "===== 操作取消 =====" |
|
exit 0 |
|
;; |
|
esac |
|
fi |
|
|
|
# --- 开始安装流程 --- |
|
# 1. 安装编译依赖 |
|
echo -e "\n===== 1. 安装编译依赖 (已包含 sqlite3, bz2, lzma, tk 等支持) =====" |
|
sudo apt-get update |
|
sudo apt-get install -y build-essential zlib1g-dev libncurses5-dev \ |
|
libgdbm-dev libnss3-dev libssl-dev libreadline-dev \ |
|
libffi-dev libsqlite3-dev tk-dev libbz2-dev liblzma-dev wget |
|
|
|
# 2. 下载Python源码 |
|
echo -e "\n===== 2. 下载Python ${PYTHON_VERSION} 源码 =====" |
|
wget -c "${DOWNLOAD_URL}" -O "Python-${PYTHON_VERSION}.tgz" || { echo "错误: 下载失败,请检查版本号或网络"; exit 1; } |
|
|
|
# 3. 解压源码 |
|
echo -e "\n===== 3. 解压源码 =====" |
|
tar -xf "Python-${PYTHON_VERSION}.tgz" |
|
cd "Python-${PYTHON_VERSION}" || { echo "错误: 解压目录不存在"; exit 1; } |
|
|
|
# 4. 配置、编译、安装 |
|
echo -e "\n===== 4. 配置编译参数 =====" |
|
./configure --prefix="${INSTALL_PREFIX}" --enable-optimizations --with-ensurepip=install |
|
echo -e "\n===== 5. 开始编译 (这可能需要几分钟时间) =====" |
|
make -j $(nproc) |
|
echo -e "\n===== 6. 开始安装 =====" |
|
sudo make altinstall |
|
|
|
# 7. 验证安装 |
|
echo -e "\n===== 7. 验证安装 =====" |
|
if [ -f "${PYTHON_BIN}" ]; then |
|
echo -e "✅ Python ${PYTHON_VERSION} 安装成功!" |
|
"${PYTHON_BIN}" --version |
|
echo -n "✅ pip 安装成功! 版本: " |
|
"${PIP_BIN}" --version |
|
echo -n "✅ 验证 sqlite3 模块... " |
|
if "${PYTHON_BIN}" -c "import sqlite3" &> /dev/null; then echo "成功!"; else echo "失败!"; fi |
|
|
|
# 8. 自动设置别名 |
|
echo -e "\n===== 8. 自动设置别名到 ${RC_FILE} =====" |
|
sed -i "/alias python${MAJOR_VERSION}=/d" "$RC_FILE" |
|
sed -i "/alias pip${MAJOR_VERSION}=/d" "$RC_FILE" |
|
echo "" >> "$RC_FILE" |
|
echo "# Python ${PYTHON_VERSION} alias" >> "$RC_FILE" |
|
echo "alias python${MAJOR_VERSION}=\"${PYTHON_BIN}\"" >> "$RC_FILE" |
|
echo "alias pip${MAJOR_VERSION}=\"${PIP_BIN}\"" >> "$RC_FILE" |
|
|
|
echo -e "\n===== 🎉 安装完成! =====" |
|
echo "别名已写入 ${RC_FILE}。请在新终端中使用或执行 \`source ${RC_FILE}\`" |
|
|
|
# <<< 关键警告 >>> |
|
# 如果是重新安装,给出关于虚拟环境的重要提示 |
|
if [ "$REINSTALL_FLAG" = true ]; then |
|
echo -e "\n\n!!!!!!!!!!!!!!!!!!!! 重要警告 !!!!!!!!!!!!!!!!!!!!" |
|
echo "您刚刚重新安装了 Python ${PYTHON_VERSION}。" |
|
echo "任何之前用此版本创建的虚拟环境 (venv) 现已损坏,会导致 'encodings' 错误。" |
|
echo "您必须按以下步骤重建它们:" |
|
echo "" |
|
echo " # 1. (如果还在虚拟环境中) 退出" |
|
echo " deactivate" |
|
echo "" |
|
echo " # 2. 删除旧的虚拟环境目录 (例如,名为 .venv)" |
|
echo " rm -rf /path/to/your/project/.venv" |
|
echo "" |
|
echo " # 3. 使用新安装的 python 重新创建" |
|
echo " cd /path/to/your/project/" |
|
echo " python${MAJOR_VERSION} -m venv .venv" |
|
echo "" |
|
echo " # 4. 重新激活并安装依赖" |
|
echo " source .venv/bin/activate" |
|
echo " pip install -r requirements.txt" |
|
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" |
|
fi |
|
|
|
else |
|
echo "错误: Python 安装失败,请检查编译日志" |
|
exit 1 |
|
fi |
|
|
|
# 9. 清理 |
|
echo -e "\n===== 9. 清理临时文件 =====" |
|
cd .. |
|
rm -rf "Python-${PYTHON_VERSION}" "Python-${PYTHON_VERSION}.tgz" |
|
echo "清理完成。" |