从“conda list”输出安装所有内容

Install everything from a `conda list` output

我有一个文件,conda_env.txt,保存了 conda list 的标准输出。它具有以下结构。

conda_env.txt

# packages in environment at /scratch/hello/anaconda3:
#
# Name                    Version                   Build  Channel
_ipyw_jlab_nb_ext_conf    0.1.0                    py37_0
absl-py                   0.7.1                    pypi_0    pypi
alabaster                 0.7.12                   py37_0
anaconda-client           1.7.2                    py37_0
anaconda-navigator        1.9.7                    py37_0
anaconda-project          0.8.2                    py37_0
annoy                     1.14.0                   pypi_0    pypi

我想要conda install此文件中列出的所有软件包,并指定版本。

我的想法是for循环遍历所有行(从第4行开始),从第一个和第二个字段中获取值,并将它们保存到PACKAGEVERSION中,然后安装通过调用 conda install $PACKAGE=$VERSION(例如,conda install pandas=0.20.3

我想编写一个 shell 脚本来执行此操作。我写了一个演示文件只是为了读取第 i 行和它的第二个字段:

#!/bin/bash
LINES=$(wc -l < conda_env.txt)
for i in {4...10}
do
awk -F '|' 'NR==${i}{print }' conda_env.txt
done

它给我错误:awk: bailing out at source line 1

知道这里出了什么问题以及如何正确处理吗?

请您尝试以下操作:

#!/bin/bash

while read -r package version _; do
    [[ $package = "#"* ]] && continue           # skip the comment lines
    # remove "echo" if the output looks good
    echo conda install "$package=$version"
done < "conda_env.txt"

输出:

conda install _ipyw_jlab_nb_ext_conf=0.1.0
conda install absl-py=0.7.1
conda install alabaster=0.7.12
conda install anaconda-client=1.7.2
conda install anaconda-navigator=1.9.7
conda install anaconda-project=0.8.2
conda install annoy=1.14.0

如果输出行符合您的预期,则删除 echo 并执行脚本。

转换为 YAML

我写了 an AWK script 来将 conda list 的输出转换为与 conda env create -f env.yaml 兼容的 YAML。这应该比一系列 conda install 调用更受青睐,后者导致 运行 对每个单独的包进行求解。

AWK 脚本

list_to_yaml.awk

#!/usr/bin/env awk -f
#' Author: Mervin Fansler
#' GitHub: @mfansler
#' License: MIT

#' Usage
#' $ conda list | awk -f list_to_yaml.awk

{
  # skip header
  if ( ~ /^#/) { next }

  if ( ~ /pypi/) {  # pypi packages
    pip=1;
    pypi[i++]="    - ""=="" ";
  } else {  # conda packages
    if ( ~ /pip/) {
      pip=1;
    } else {
      conda[j++]="  - ""="" ";
    }
    
    # include channels
    if (!seen[]) {
      if (length() == 0) {
        channels[k++]="  - defaults ";
      } else {
        channels[k++]="  - "" ";
      }
      ++seen[];
    }
  }
}
END {
  # emit channel info
  print "channels: ";
  for (k in channels) print channels[k];
  
  # emit conda pkg info                                                                                                               
  print "dependencies: ";
  for (j in conda) print conda[j];

  # emit PyPI pkg info
  if (pip) print "  - pip ";
  if (length(pypi) > 0) {
    print "  - pip: ";
    for (i in pypi) print pypi[i];
  }
}

用法

假设我们有一个环境foo,有人为(foo_list.txt)转储了一个conda list,我们可以创建一个相应的YAML文件(foo.yaml), 然后用它来生成一个新的环境, bar.

# dump a `conda list` for environment `foo`
conda list -n foo > foo_list.txt

# convert to YAML
awk -f list_to_yaml.awk foo_list.txt > foo.yaml

# edit the foo.yaml channels section manually!
# usually should be `conda-forge` at the top, `defaults` at the bottom
# emacs foo.yaml

# create the new environment
conda env create -n bar -f foo.yaml

或者,如果您只是想测试一下,管道也可以:

conda list -n foo | awk -f list_to_yaml.awk

优势

  • 自动处理来自 PyPI 的包
  • 处理频道(排序;顺序可能不是最佳的)
  • 为安装创建单个文件
  • 不会重复调用 conda install,这会导致大量不必要的求解