最可靠方式是用 subprocess.run 调用 pip show package_name 并解析 Version 行,需捕获 CalledProcessError 处理包未安装情况;内存检查应使用 psutil.virtual_memory().available 而非 total,因 available 反映实际可用内存,避免缓存干扰。

怎么用 subprocess 安全获取已安装包版本
直接调用 pip show package_name 最可靠,比解析 pip list 输出更精准——后者容易匹配到子包或名称相似项。注意捕获异常,subprocess.run 的 check=True 会抛出 CalledProcessError,而包未安装时返回非零码,必须显式处理:
import subprocess
def get_package_version(pkg):
try:
result = subprocess.run(
["pip", "show", pkg],
capture_output=True,
text=True,
check=True
)
for line in result.stdout.splitlines():
if line.startswith("Version:"):
return line.split(":", 1)[1].strip()
return None
except subprocess.CalledProcessError:
return None # 包未安装
别用 os.popen 或 os.system,它们不便于错误控制;也别在生产脚本里硬编码 pip3,统一用 pip 更兼容虚拟环境。
内存检查为什么不能只看 psutil.virtual_memory().total
这个值是物理内存总量,但自动化检查真正关心的是「当前可用内存是否足以启动服务」,得看 available(Linux/Windows/macOS 都支持),它反映内核认为可立即分配的字节数,已排除缓存、buffers 等不可靠部分。用 total 容易误报——比如机器有 16GB 内存但被缓存占满,实际只剩 500MB 可用,total 仍显示 16GB。
示例判断逻辑:
立即学习“Python免费学习笔记(深入)”;
import psutil
mem = psutil.virtual_memory()
if mem.available < 2 * 1024**3: # 小于 2GB
print("警告:可用内存不足 2GB")
- 单位始终是字节,别漏掉
1024**3换算 GB - 避免用
psutil.sensors_memory(),它在 macOS 和 Windows 上不可用 - 如果脚本需在容器中运行,
available仍有效,但注意 cgroup 限制可能让该值小于宿主机总内存
校验多个依赖时怎么避免重复执行 pip show
每调一次 pip show 都要 fork 进程、加载 pip 模块,开销不小。把所有待查包名一次性传给 pip show,它支持多参数:
result = subprocess.run(
["pip", "show", "requests", "numpy", "pyyaml"],
capture_output=True,
text=True
)
# 然后按分隔符 "\n\n" 拆分各包输出
这样一次调用就能拿到全部结果。注意:pip show 对不存在的包会静默跳过(不报错),所以必须检查输出中是否包含对应包的 Name: 段落,不能只依赖返回码。
更稳妥的做法是先用 pip list --format=freeze 获取全量清单,再本地解析——适合检查几十个包的场景,但要注意格式兼容性(不同 pip 版本对 --format 支持略有差异)。
脚本退出码怎么设计才利于 CI/CD 判断
别统一用 sys.exit(0) 或 1。建议分层编码:
-
0:全部通过 -
10:至少一个依赖版本不满足(如requests) -
20:至少一个依赖未安装 -
30:内存不足
CI 工具(如 GitHub Actions、Jenkins)能根据 exit code 做分支判断。例如在 GitHub Actions 中写 if: ${{ failure() && steps.check.outputs.code == '10' }} 单独处理版本问题。别把所有失败都塞进 1,否则后续无法区分是缺包还是内存炸了。
真实环境中,内存阈值和依赖版本要求往往随部署目标变化,这些值最好从环境变量或 JSON 配置文件读取,而不是硬编码在脚本里。


















