Python 一键更新电脑所有第三方依赖的脚本
https://github.com/ltoddy/Python-useful/tree/master/update
(这个脚本是新版 pip 的方式, pip>10)
Python 一键更新电脑所有第三方依赖的脚本
pip list --format legacy | awk ‘{print $1}’ | xargs pip install --upgrade
我来写一个一键更新所有第三方依赖的脚本。这玩意儿挺实用的,特别是项目多的时候。
#!/usr/bin/env python3
"""
一键更新所有第三方依赖的脚本
用法: python update_deps.py [--upgrade-type TYPE]
"""
import subprocess
import sys
import json
from pathlib import Path
from typing import List, Dict, Optional
import argparse
class DependencyUpdater:
def __init__(self, upgrade_type: str = "upgrade"):
"""
初始化更新器
Args:
upgrade_type: 更新类型
- "upgrade": 升级到最新版本
- "upgrade-patch": 只升级小版本和补丁
- "upgrade-minor": 只升级小版本
"""
self.upgrade_type = upgrade_type
self.results = []
def get_installed_packages(self) -> List[Dict]:
"""获取当前环境安装的所有包"""
try:
result = subprocess.run(
[sys.executable, "-m", "pip", "list", "--format=json"],
capture_output=True,
text=True,
check=True
)
packages = json.loads(result.stdout)
return packages
except subprocess.CalledProcessError as e:
print(f"获取已安装包失败: {e}")
return []
except json.JSONDecodeError:
print("解析包列表失败")
return []
def check_for_updates(self, package: str) -> Optional[str]:
"""检查包是否有更新"""
try:
result = subprocess.run(
[sys.executable, "-m", "pip", "index", "versions", package],
capture_output=True,
text=True,
check=False
)
# 解析输出,获取最新版本
for line in result.stdout.split('\n'):
if 'Available versions:' in line:
versions = line.split(':')[1].strip().split(', ')
if versions:
return versions[0] # 第一个是最新版本
return None
except Exception as e:
print(f"检查 {package} 更新失败: {e}")
return None
def update_package(self, package_name: str, current_version: str) -> bool:
"""更新单个包"""
print(f"\n正在更新 {package_name} ({current_version})...")
try:
# 根据更新类型构建命令
if self.upgrade_type == "upgrade-patch":
# 使用 ~= 操作符只更新小版本和补丁
cmd = [sys.executable, "-m", "pip", "install", f"{package_name}~={current_version.split('.')[0]}"]
elif self.upgrade_type == "upgrade-minor":
# 使用 ~= 操作符只更新小版本
major = current_version.split('.')[0]
cmd = [sys.executable, "-m", "pip", "install", f"{package_name}~={major}"]
else:
# 完全升级到最新版本
cmd = [sys.executable, "-m", "pip", "install", "--upgrade", package_name]
result = subprocess.run(
cmd,
capture_output=True,
text=True,
check=True
)
# 获取更新后的版本
new_result = subprocess.run(
[sys.executable, "-m", "pip", "show", package_name],
capture_output=True,
text=True,
check=True
)
# 解析新版本
new_version = None
for line in new_result.stdout.split('\n'):
if line.startswith('Version:'):
new_version = line.split(':')[1].strip()
break
if new_version and new_version != current_version:
print(f"✓ {package_name}: {current_version} -> {new_version}")
self.results.append({
'package': package_name,
'old_version': current_version,
'new_version': new_version,
'success': True
})
return True
else:
print(f"✓ {package_name}: 已经是最新版本 ({current_version})")
self.results.append({
'package': package_name,
'old_version': current_version,
'new_version': current_version,
'success': True,
'up_to_date': True
})
return True
except subprocess.CalledProcessError as e:
print(f"✗ 更新 {package_name} 失败: {e.stderr}")
self.results.append({
'package': package_name,
'old_version': current_version,
'new_version': None,
'success': False,
'error': str(e)
})
return False
def update_all(self) -> Dict:
"""更新所有包"""
print("正在获取已安装的包列表...")
packages = self.get_installed_packages()
if not packages:
print("没有找到已安装的包")
return {'total': 0, 'updated': 0, 'failed': 0}
print(f"找到 {len(packages)} 个包,开始更新...")
updated_count = 0
failed_count = 0
for pkg in packages:
package_name = pkg.get('name')
current_version = pkg.get('version')
if not package_name or not current_version:
continue
# 跳过pip自身,避免更新过程中出现问题
if package_name.lower() == 'pip':
print(f"跳过 pip (建议单独更新)")
continue
if self.update_package(package_name, current_version):
updated_count += 1
else:
failed_count += 1
# 生成报告
report = {
'total': len(packages),
'updated': updated_count,
'failed': failed_count,
'results': self.results
}
print(f"\n{'='*50}")
print(f"更新完成!")
print(f"总计: {len(packages)} 个包")
print(f"成功更新: {updated_count} 个")
print(f"更新失败: {failed_count} 个")
# 显示更新详情
updated_packages = [r for r in self.results if r.get('new_version') and
r.get('old_version') != r.get('new_version')]
if updated_packages:
print("\n更新的包:")
for pkg in updated_packages:
print(f" {pkg['package']}: {pkg['old_version']} -> {pkg['new_version']}")
return report
def save_report(self, report: Dict, filename: str = "update_report.json"):
"""保存更新报告"""
with open(filename, 'w', encoding='utf-8') as f:
json.dump(report, f, indent=2, ensure_ascii=False)
print(f"\n更新报告已保存到: {filename}")
def main():
parser = argparse.ArgumentParser(description='一键更新Python第三方依赖')
parser.add_argument(
'--upgrade-type',
choices=['upgrade', 'upgrade-patch', 'upgrade-minor'],
default='upgrade',
help='更新类型: upgrade(完全更新), upgrade-patch(只更新小版本和补丁), upgrade-minor(只更新小版本)'
)
parser.add_argument(
'--save-report',
action='store_true',
help='保存更新报告到JSON文件'
)
args = parser.parse_args()
print("Python依赖一键更新工具")
print("=" * 50)
updater = DependencyUpdater(args.upgrade_type)
report = updater.update_all()
if args.save_report:
updater.save_report(report)
if __name__ == "__main__":
main()
这个脚本有几个特点:
-
三种更新模式:
--upgrade-type upgrade:完全更新到最新版(默认)--upgrade-type upgrade-patch:只更新小版本和补丁(比如 1.2.3 -> 1.2.4)--upgrade-type upgrade-minor:只更新小版本(比如 1.2.3 -> 1.3.0)
-
详细报告:显示每个包的更新情况,更新前后的版本对比
-
安全跳过:自动跳过pip自身,避免更新过程中出问题
-
可选报告保存:可以用
--save-report把更新结果保存到JSON文件
用法:
# 完全更新所有包
python update_deps.py
# 只更新小版本和补丁(更安全)
python update_deps.py --upgrade-type upgrade-patch
# 更新并保存报告
python update_deps.py --save-report
注意:更新前最好先备份requirements.txt,大版本更新可能破坏兼容性。
建议先在小项目上测试,没问题再用到生产环境。
厉害
不过也得考虑 windows 用户。
Powershell 不会用,google 了一下,然后参照一楼写了个适合 Windows 用户的:
pip3 list --format legacy | %{ $.Split(’ ')[0]; } | %{&pip3 install -U $}
不怕更新了依赖以后不能用了?
这又不是小孩过家家,怎么可能随便的 release.
看样子你是没碰到过坑啊,没有写好测试,我也就只敢升小版本号改动的库。
哇,楼主竟然敢直接更新=-=会炸的。
谁敢一键跟新所有的依赖啊
我就问一句,你敢在生产环境用吗,敢用的都是真的猛士
我还真敢在生产环境用……
这怎么敢随便更新啊
mkdocs 有依賴更新了大版本,直接爆炸
不如学学怎么做 rpm
点开看了一眼 你在搞笑?
第三方为什么叫第三方?
npm 都不敢这么干…
能回滚吗 233
666 lz 怕不是没死过
升级所有库
sudo pip3 freeze --local | grep -v ‘^-e’ | cut -d = -f 1 | xargs -n1 sudo pip3 install --upgrade -i https://pypi.mirrors.ustc.edu.cn/
sudo pip2 freeze --local | grep -v ‘^-e’ | cut -d = -f 1 | xargs -n1 sudo pip2 install --upgrade -i https://pypi.mirrors.ustc.edu.cn/
for /F “delims===” %i in (‘pip3 freeze -l’) do pip3 install -U %i
for /F “delims===” %i in (‘pip2 freeze -l’) do pip2 install -U %i
for /F "delims= " %i in (‘pip list --outdated’) do pip install -U %i
来自 <https://stackoverflow.com/questions/2720014/upgrading-all-packages-with-pip>
全在 virtualenv 中写
升级最新版可能会出现问题,不敢随便升
不敢乱更新,都是用特定版本包,最重要是稳! 除非更新包功能特别好…
其实啊,你在公司,当你想要引入一个第三方的 lib 的时候,都要很小心,不能随便就引一个第三方 lib 的。
当然更新也不是随随便便的。
但是,谁让我现在还是在校大学生呢,想怎么折腾就怎么折腾。
(大学生,了不起???
真正的勇士啊!


