升级时拖动已安装的 Python 包

升级时拖动已安装的 Python 包

作为一个运行多个 Web 服务器(每个服务器都运行一组 Django 网站)的人,掌握 Python 堆栈非常重要。出于(可能不好的)习惯,我依赖 Ubuntu 来运行我的许多 Python 包,包括python-django许多python-django-*额外的包。网站需要这些包才能运行,但只要包仍然存在,这不是问题。我这样做而不是使用 VirtualEnv(等),因为我Ubuntu 安装安全更新。

但是 Ubuntu 存储库并不适合所有人。有些情况下我会使用pipeasy_install安装最新版本的 Python 包。当你更新 Python 时(Ubuntu 中偶尔会发生这种情况),你会丢失所有pip已安装的包。

让我害怕的是,我越深入,管理的服务器越多,总有一天会有一个操作系统更新,需要我花上几个小时跑来跑去,测试网站,通过重新安装python包pip。最糟糕的是客户网站可能会停机,尽管我确实在我的开发机器上测试过(总是在最新的Ubuntu上),所以这应该可以抵消一些担忧。

我可以做些什么来确保 Python 的更新意味着现有的非 dpgk 的 Python 包会被提前?

这样可以确保我始终可以访问相同的软件包。我仍然需要测试不兼容性,但这将是一个好的开始。

也许有一个更好的解决方案:一个行为类似aptdpkg用于与PyPi(在哪里pip获取easy_install他们的大部分魔力)。存储本地已安装软件包列表、检查更新(如)apt、管理安装等的东西。这样的事情存在吗?或者说这是一个糟糕的想法?

答案1

关于如何在系统 Python 升级时保留你的 Python 包:我看到两个选项:

  1. 您可以使用安装非 Ubuntu Python 的东西easy_install --install-dir /usr/local/python然后确保所有 web 应用程序都将该目录包含到中sys.path,例如将其包含到 PYTHONPATH 中,或者使用自动包含的目录site.py(其文档指出“本地插件进入/usr/local/lib/python<version>/dist-packages”)

  2. 你可以使用 virtualenvs,只要你能将所有应用数据和配置放在独立于代码的目录中即可。以下是草图流程:

    a. 将所有与代码无关的内容放入目录中 myapp-data/

    b. 创建虚拟环境myapp-code.XXX/(其中XXX是某个唯一版本号,例如date -I

    c. 将应用程序代码和所有依赖包放在myapp-code.XXX

    d.ln -s myapp-code.XXX myapp-code

    当你需要升级时,只需使用不同的修订代码 YYY 重复步骤 b. 和 c.,然后:停止当前正在运行的应用程序,符号链接myapp-codemyapp-code.YYY,从虚拟环境启动应用程序 myapp-code.YYY。如果出现问题,你仍然可以快速回滚到旧的虚拟环境。

显然,2. 的工作量更大(但pip加上一些 shell 脚本将使您在很大程度上实现自动化),但它也应该更加健壮,并允许您同时运行依赖于某些 Python 包的不同版本的应用程序。

关于您对apt-getPython 软件包的 -like 的问题: pip明确禁止这样做,原因很充分:软件包 API 和行为可能会因版本不同而发生变化。因此,如果您的代码在版本 X 上运行良好,则在版本 X+1 上运行时可能会失败。这正是pip其“冻结”和“需求列表”功能试图防止的情况。

当然,同样的论点可以应用于像 Ubuntu 这样的二进制发行版中的任何程序;事实上,有用的apt-get是 Debian 和 Ubuntu 提供了一个协调发布可互操作的软件包:维护人员付出了很多努力来确保主存储库中的所有 Ubuntu 软件包都是兼容的。

Python 软件包根本没有这种协调发布:每个软件包都是独立的,并且没有关于其他 Python 软件包的哪个版本与其兼容的信息。(这可能是 PyPI 元数据的一个很好的补充。)

答案2

我将使用如下配置管理系统木偶或者厨师在所有服务器上运行脚本,使它们保持同步。您的脚本(配方)可以管理升级,包括自动测试升级是否成功或发生故障。

相关内容