【问题标题】:Mess with venv or new flavor of python?与 venv 或新风格的 python 混在一起?
【发布时间】:2019-02-04 10:03:51
【问题描述】:

问题

问题是,是否有其他我没有想到的方法来解决下面的这些问题,或者它真的是使用我们的工具构建 python 风格的答案吗?我有一个解决问题的建议解决方案,但这并不意味着它是正确的答案。

问题

我在一个支持组织工作,我们正在开发工具来支持我们的主要产品。这个产品有它自己运行的操作系统。我们在包装中需要解决三个不同的问题 o

  1. OS 的风格具有我们可以安装到的原始 python 二进制文件,但这限制了我们使用 python 的 OS 版本,它将作为一个单独的团队来管理 OS。预计在接下来的 2 年中,python 3.4、3.5 和 3.6 版本之间的情况会发生变化——这些变化会影响我们一贯使用的库,无论好坏。

  2. 我们构建的工具也可在没有外部连接的站点上用作独立工具进行分析。我们目前仅限于“希望无论他们在哪里使用的 python 都能玩得很好”。

  3. 我们希望利用更高版本的 python 的显着性能改进,并且不能不升级到 3.6,但这会消除我们使用旧版本的能力,因为在将事情一一打破的python库。

我最初的方法是尝试制作一个可重定位的独立 virtualenv,但是我查看该代码的次数越多,我发现它只是在编辑 PYTHONHOME 和 PATH,如果你希望它是可重定位的,你有无论如何都要复制所有二进制文件,或者只有在主机具有您构建的python版本时才可用。这也有缺点,需要对 virtualenv 脚本进行大量修改,以便修改 shebangs、更新路径等 - 并且需要在每次移动时更新,或者具有动态 shebangs。

感觉不对的建议解决方案

现在我正在考虑创造我们自己的“风味”蟒蛇 - 但这感觉就像在晚宴上用斧头切胡萝卜一样。它解决了可以使用的多个位置的所有问题,所有位置都具有与我们安装的工具一致的最新版本的 python,因此所有用户需要做的就是运行一个脚本来更新 PATH 与/bin 安装这些东西的地方。

回到问题:

是否有其他我没有想到的方法来解决这些问题,或者它真的是使用我们的工具构建 Python 风格的答案吗?我是否因为缺乏经验而感到错误,或者这是我应该考虑的有效答案?

【问题讨论】:

  • 你通常会使用tox - 你已经检查过了吗?
  • 您能否在您的环境中安装自己构建 python 版本所需的开发工具?
  • 为什么不使用 py2exe 或 nuitka 或类似工具将所有内容(您的应用程序和相应版本的 python)自动捆绑到单个应用程序/捆绑包中?
  • 我不知道 tox 是一回事 - 我太忙于专注于可重定位的 virtualenvs 并且似乎已经戴上了一些我需要移除的眼罩,因为我知道 virtualenv 不会做我想做的事需要。我会看看这些替代方案。
  • 我是否误解了这一点,因为 tox 要求二进制文件已经在主机上?需要明确的是 - 我需要它与 3.6.6 独立。独立是其中的重要方面 - 不一定是 python 版本。 Nuitka 不会通过我们的安全人员——我可以通过一个普通的 3.6.6 二进制文件,但一个新的编译器在幕后执行它自己的魔法不是一个选择。 py2exe 以 Windows 为中心,我们需要它独立于平台。到目前为止,python 的味道似乎是一次解决我所有问题的答案。

标签: python python-3.x virtualenv python-packaging


【解决方案1】:

您实际上可以在本地将 Python 安装到没有 root 权限的目录中,并完全独立于任何系统 Python 运行它。您的工具可以使用这个独立的 Python 安装,而不是任何类型的系统级依赖项。

  • 使用tar -xzf Python-X.X.X.tgz解压Python版本
  • 使用mkdir ~/python36为安装的Python创建一个目录
  • 使用cd Python-X.X.X进入解压后的安装文件目录
  • 使用./configure -prefix=/home/user/python36 为您的系统生成 Python 生成文件
  • 使用 make altinstall prefix=/home/user/python36 exec-prefix=/home/user/python36 将 Python 安装到本地目录(注意使用 altinstall 很关键,因为这样可以确保不替换 Linux 依赖 Python 2.7 或其他已安装版本)

现在,您可以使用/home/user/python36/bin/python3 script.py 在此本地安装上运行您的项目。使用此方法,您可以使用一个版本的 Python 进行开发,而不必预期您无法控制的更改。如果您想为 your 工具更新 your Python,这是一个非常有目的性和原子性的操作。

【讨论】:

  • 结束了这个和 docker,所以我不必继续下载图像 - 现在我有一个基础 docker 图像,其中已在目标版本上安装了二进制文件 - 从我们的 repo 中提取更新,使用 pip 安装它们就可以了,并将新安装的二进制文件打包到一个挂载的文件夹中,并将它们作为构建/测试的工件。
  • 发布了使可重定位真正成为可能的 virtualenv 激活脚本更改的细节。
【解决方案2】:

类似于 J. Blackadar 的回答,我知道至少有一家公司这样做。

Heroku 是一家云提供商,它有一个用 NodeJS 编写的 CLI 工具。 Heroku 使用自制软件分发包。他们还使用相同的包管理器来分发他们自己的 nodejs 版本,名为 heroku/brew/node。你可以看到有时程序本身会更新,当 NodeJS 有更新时,它们都会更新。问题是,有时 NodeJS 本身会更新,但 heroku 不会更新它自己的 NodeJS,因此他们可以继续使用自己的版本,直到他们使用新版本运行适当的测试。

你也可以安装自己的python版本并单独更新或者使用virtualenv安装特定版本的python,不过相信你已经试过了。

另一种选择是使用 docker 当然,您将在任何地方拥有相同的环境,但是由于您有一个特殊的操作系统,这可能会增加更多的复杂性。

【讨论】:

    【解决方案3】:

    我实际上最终混合了这两者 - 我创建了我自己的“激活”文件,该文件动态分配路径(无论激活文件被调用什么,都具有一些附加功能,并将其放入 python 二进制文件中。来源时,它将更新shebangs。

    1. activate 现在将动态设置路径,使用它自己的目录 它作为新的 PATH 垫片驻留在其中。这假设,与大多数 venvs,激活脚本驻留在 bin 中。

    2. activate 现在有一个帮助脚本和一个为所有人调用它的包装器 bin 中具有 shebang 的文件。它将这些文件更新为 当前 python 可执行文件的路径(应该是 此时由 virtualenv 激活脚本更新)。它会 仅当 shebang 不同时才这样做。

    脚本更改以供参考:

    function update_shebang() {
        # Call like: update_shebang check_sas_cabling
        full_path=${1}
        # Back up our scripts, making them hidden by default.
        file_dir=$(dirname $full_path)
        file_name=$(basename $full_path)
        cp ${full_path} "${file_dir}/.${file_name}.bak"
        # Find old shebang - will look something like this:
        # /workdir/pure_python/bin/python3
        oldbang=$(grep '#!' ${full_path})
        newbang_path=$(readlink -f `which python`)
        # We have to escape the !, but then it keeps the backslash, so we have to
        # get rid of it.
        newbang=$(echo "#\!$newbang_path" | tr -d '\\')
        # Just using sed in place
        # We dont' want to spam people every time they activate - so only modify
        # them if they aren't the same.
        if [ "$(echo $oldbang | tr -d "/")" != "$(echo $newbang | tr -d "/")" ]; then
            # Don't modify binary matches.
            if [ ! "$(echo $oldbang | grep 'Binary')" ]; then
                echo "Updated shebang for ${file_name} from ${oldbang} to ${newbang}"
                sed -i "s|${oldbang}|${newbang}|" ${full_path}
            fi
        fi
    }
    
    function update_all_shebangs() {
        # Wrapper around update_shebang to update all the
        # shebangs in ${NEW_PATH}/bin.
        given_path=$1
        myfiles=$(ls $given_path | grep -ve "^activate$")
        for file in $myfiles; do
            fullpath=$given_path/$file
            if grep -q "#!" $fullpath; then
                update_shebang $fullpath || exit 1
            fi
        done
    }
    

    还有新的动态路径部分:

    NEW_PATH="$(dirname $(dirname $(readlink -f -n $BASH_SOURCE)))"
    

    我还在一个 docker 镜像中创建了这个,该镜像运行了我所需的所有 pip 安装,然后将它与所有这些捆绑在一起 - 所以它需要更长的时间,但在所有意义上都可以重新定位正确开箱即用。

    一旦我编写了所需的 docker 安装脚本,将建立包含此内容的骨架 repo。 :D

    【讨论】:

      猜你喜欢
      • 2019-11-09
      • 2013-02-19
      • 2019-11-13
      • 1970-01-01
      • 2014-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多