为许多机器复制使用 venv 创建的文件夹以使用环境的替代方法

Alternatives to copying the folder created with venv for many machines to use the environment

我有大约 30 台机器,我计划将它们全部用于 运行 分布式训练 python script.They 所有机器都具有相同的用户名,以防万一。我在 Windows 并且需要使用 GPU 以防这也有帮助。它们都具有相同的 python 版本和必要的软件安装,但我需要它们安装相同版本的模块(pandas、matplotlib 等)。

我的做法:我一开始用一台机器运行python -m venv myenv然后做了pip install -r requirements.txt。我将文件夹放在网络驱动器中,并让所有机器将目录更改为该网络驱动器。因为他们都有相同的用户名,所以我觉得没关系。它对其中几个有效,但对所有无效。替代解决方案是让所有机器 运行 命令 python -m venv myenv pip install -r requirements.txt 但这不是很理想吗?如果我必须添加一个模块怎么办?有人有什么建议吗?

编辑:我希望有一个 Docker 的替代解决方案。

也许您可以使用 conda 环境并将其导出:

conda-env export -n myenvnaame > myenvfile.yml

然后在其他机器上导入:

conda-env create -n venv -f=myenvfile.yml

或者您可以使用 docker 并在所有机器上共享图像

虽然这稍微超出了 pure-python 的范围,但为执行创建一个 docker 容器,使用构建指令完成设置,将允许该 venv 与其周围环境完全隔离机器设置。

Docker 允许同一个框上的多个实例 运行 共享相同的定义,因此如果您遇到 运行 相同代码的 5 个副本,它可以为共享内存代码运行时重新使用相同的内存 IIRC。我读过这篇文章,但还没有尝试过内存规格。

30 台机器是相当多的手动管理机器。大概您可以通过 SSH 访问它们,并且正在考虑将应用程序批量部署到所有这些应用程序的一些解决方案。

这听起来像是 Ansible. If you're not familiar with, I recommend to check it out and investigate how well it works with Windows hosts (personally I have only used it with Linux machines; FAQ for Windows) 的完美用例。它有一点学习曲线,但是一旦您准备好将应用程序部署到一台机器上的工作手册,您就可以扩展主机列表并将完全相同的东西部署到所有 30 台机器上。

基本上我会创建一个剧本来让每台机器创建一个具有依赖关系的本地虚拟环境,但我会从单个节点管理它们。

示例剧本:

---

- name: Do stuff
  gather_facts: false
  hosts: all
  vars:
    virtual_environment: "/home/pi/test_env"

  tasks:
    - name: Install low-level dependencies
      become: true
      apt:
        name: libatlas-base-dev
        update_cache: yes

    - name: Install pip dependencies
      pip:
        name:
          - pandas
          - matplotlib
          - numpy
        virtualenv: "{{ virtual_environment }}"
        virtualenv_command: python3 -m venv

    - name: Execute some script
      command:
        cmd: |
          {{ virtual_environment }}/bin/python -c '
          import pandas as pd
          print("Pandas is installed under:", pd.__file__)
          '
      register: script

    - name: Print the output
      debug:
        msg: "{{ script.stdout }}"

样本清单:

192.168.0.24

输出:

$ ansible-playbook -i inventory playbook.yml

PLAY [Do stuff] **************************************************************************

TASK [Install low-level dependencies] ****************************************************
ok: [192.168.0.24]

TASK [Install pip dependencies] **********************************************************
ok: [192.168.0.24]

TASK [Execute some script] ***************************************************************
changed: [192.168.0.24]

TASK [Print the output] ******************************************************************
ok: [192.168.0.24] => {
    "msg": "Pandas is installed under: /home/pi/test_env/lib/python3.7/site-packages/pandas/__init__.py"
}

PLAY RECAP *******************************************************************************
192.168.0.24               : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

请注意,对于大多数任务来说,这个 运行 是如何导致“ok”而不是“changed”的——这是因为我之前已经 运行 这个 playbook 而这次 Ansible 注意到包是已经安装了,所以不需要重新安装。大多数 Ansible 模块都是以这种方式设置的,因此效率很高。请参阅(非常好!)文档以找出每个模块可用的参数(在上面的示例中,模块是:aptpipcommanddebug).