2.4. 输入 (inputs)#

2.4.1. 基本输入参数#

工具的 inputs(输入)用于列出控制工具运行方式的输入参数。每个参数都包含 id 字段作为名称,以及 type 字段描述有效参数值的类型。

可用的原始类型有 string(字符串)、boolean(布尔变量)、int(整型)、long(长整型)、 float(浮点数)、double(双精度浮点数)以及 null(空)等;复合类型指的是 array(数组)和 record(记录);此外还有特殊类型 File(文件)、Directory(目录)以及 Any(任意)等。

下面的例子展示了一些类型各异、以不同方式出现在命令行上的输入参数。

首先,创建一个名为 inp.cwl 的文件,包含以下内容:

inp.cwl#
#!/usr/bin/env cwl-runner
cwlVersion: v1.2
class: CommandLineTool
baseCommand: echo
inputs:
  example_flag:
    type: boolean
    inputBinding:
      position: 1
      prefix: -f
  example_string:
    type: string
    inputBinding:
      position: 3
      prefix: --example-string
  example_int:
    type: int
    inputBinding:
      position: 2
      prefix: -i
      separate: false
  example_file:
    type: File?
    inputBinding:
      prefix: --file=
      separate: false
      position: 4

outputs: []

创建名为 inp-job.yml 的文件:

inp-job.yml#
example_flag: true
example_string: hello
example_int: 42
example_file:
  class: File
  path: whale.txt

备注

您可以用 cwltool 创建模板输入对象,以免在输入对象文件中写入全部输入参数:

$ cwltool --make-template inp.cwl
INFO /home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/envs/latest/bin/cwltool 3.2.20260411152607
INFO Resolved 'inp.cwl' to 'file:///home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/checkouts/latest/src/_includes/cwl/inputs/inp.cwl'
example_string: a_string  # type 'string'
example_int: 0  # type 'int'
example_flag: false  # type 'boolean'
example_file:  # type 'File' (optional)
    class: File
    path: a/file/path

您可将输出重定向到一个文件:cwltool --make-template inp.cwl > inp-job.yml,然后将生成的默认值改为您想要的输入值。

注意,“example_file” 属于 File(文件)类型,因此必须作为含有 class: Filepath 字段的对象出现。

然后,在命令行键入 touch whale.txt, 用 touch 命令创建文件 whale.txt.

$ touch whale.txt

现在,使用 cwltool inp.cwl inp-job.yml 命令,即指定工具描述和输入对象、通过命令行调用 cwltool. 下方文本框描述了这两个命令及命令行的预期输出:

$ cwltool inp.cwl inp-job.yml
INFO /home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/envs/latest/bin/cwltool 3.2.20260411152607
INFO Resolved 'inp.cwl' to 'file:///home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/checkouts/latest/src/_includes/cwl/inputs/inp.cwl'
INFO [job inp.cwl] /tmp/rff6z9w3$ echo \
    -f \
    -i42 \
    --example-string \
    hello \
    --file=/tmp/i8nnhemf/stged88e7c9-3e41-48c2-8476-54333881c639/whale.txt
-f -i42 --example-string hello --file=/tmp/i8nnhemf/stged88e7c9-3e41-48c2-8476-54333881c639/whale.txt
INFO [job inp.cwl] completed success
{}INFO Final process status is success

小技巧

Where did those `/tmp` paths come from?

CWL 参考运行程序 (cwltool) 和其他运行程序会建立临时目录,在其中创建指向您文件的符号链接(又称“软”链接),以防工具意外访问未经明文指定的文件

字段 inputBinding 为可选项,用来说明该输入参数是否应出现在工具的命令行上、以何种方式出现。 如果没有 inputBinding, 则该参数不会出现在命令行上。 我们来仔细看看每个示例。

example_flag:
  type: boolean
  inputBinding:
    position: 1
    prefix: -f

布尔类型的处理相当于一种“旗标”。如果输入参数“example_flag”为“true”(真),则 prefix 会被添加到命令行,否则将不添加旗标。

example_string:
  type: string
  inputBinding:
    position: 3
    prefix: --example-string

字符串类型以字面值 (literal value) 的方式出现在命令行上。 prefix 是可选的;如果提供,它将作为单独的参数,在命令行上出现在参数值之前。上例中,相应的结果是 --example-string hello.

example_int:
  type: int
  inputBinding:
    position: 2
    prefix: -i
    separate: false

整型和浮点型以其十进制表示,作为文本出现在命令行上。 若选项 separate 为 false(伪,默认为 true 真),前缀将和它的值合并为一个参数。上例中,其产物为 -i42.

example_file:
  type: File?
  inputBinding:
    prefix: --file=
    separate: false
    position: 4

文件类型在命令行上以文件路径的方式出现。参数类型末尾如有问号 ? 意指该参数为可选。上例中,这一部分的命令行产物是 --file=/tmp/random/path/whale.txt. 不过,如果输入中未提供“example_file”参数,则不会在命令行上加入任何内容。

输入文件是只读的。 如果要更新输入文件,必须将它事先复制到输出目录

position(位置)的值用于指定参数在命令行上应出现的位置 — 并非绝对位置,而是彼此间的相对顺序。这意味着,位置值不一定要连续;position 值为 1、3、5 的三个参数生成的命令行将与其值分别为 1、2、3 时相同。 多个参数可能有相同的 position 值(这种情况下由参数名进一步决定顺序),而且 position 字段本身是可选的。 默认的位置是0.

baseCommand 字段一定会出现在最终生成的命令行中,而且位于所有参数之前。

2.4.2. 数组输入#

将以数组形式出现的参数添加至命令行很简单。指定数组参数有两种办法。第一种是在 type 字段下给出 type: array, 并且用 items 定义数组中允许出现的有效数据类型。另一种办法,是在类型的名称后添加方括号 [],以表明输入参数为此类型的数组。

array-inputs.cwl#
#!/usr/bin/env cwl-runner
cwlVersion: v1.2
class: CommandLineTool
inputs:
  filesA:
    type: string[]
    inputBinding:
      prefix: -A
      position: 1

  filesB:
    type:
      type: array
      items: string
      inputBinding:
        prefix: -B=
        separate: false
    inputBinding:
      position: 2

  filesC:
    type: string[]
    inputBinding:
      prefix: -C=
      itemSeparator: ","
      separate: false
      position: 4

outputs:
  example_out:
    type: stdout
stdout: output.txt
baseCommand: echo
array-inputs-job.yml#
filesA: [one, two, three]
filesB: [four, five, six]
filesC: [seven, eight, nine]

现在,调用命令 cwltool 并为它提供工具描述和输入对象:

$ cwltool array-inputs.cwl array-inputs-job.yml
INFO /home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/envs/latest/bin/cwltool 3.2.20260411152607
INFO Resolved 'array-inputs.cwl' to 'file:///home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/checkouts/latest/src/_includes/cwl/inputs/array-inputs.cwl'
INFO [job array-inputs.cwl] /tmp/bcyxzcey$ echo \
    -A \
    one \
    two \
    three \
    -B=four \
    -B=five \
    -B=six \
    -C=seven,eight,nine > /tmp/bcyxzcey/output.txt
INFO [job array-inputs.cwl] completed success
{
    "example_out": {
        "location": "file:///home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/checkouts/latest/src/_includes/cwl/inputs/output.txt",
        "basename": "output.txt",
        "class": "File",
        "checksum": "sha1$91038e29452bc77dcd21edef90a15075f3071540",
        "size": 60,
        "path": "/home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/checkouts/latest/src/_includes/cwl/inputs/output.txt"
    }
}INFO Final process status is success
$ cat output.txt
-A one two three -B=four -B=five -B=six -C=seven,eight,nine

inputBinding 既可以出现在外部,即数组参数本身的定义中,也可以出现在内部,即数组元素的定义中。如上所示,这两种定义方式在构建命令行时所产生的行为是不一样的。另外,itemSeparator(项目分隔符)字段如果出现,则指明数组各元素的值应并入单独的一个参数,以指定的项目分隔符插入相邻的元素值之间。

请注意,在 array-inputs-job.yml 中,数组输入由方括号 [] 指定。表达数组的另一种形式是多行句法,即用行首的 - 标明数组元素,示意它并非键值。下一课中将演示后一种用法,在《YAML 指南》 中也有详细讨论。可以指定的数组包括数组的数组、记录的数组及其他复合类型的数组。

2.4.3. 相容和互斥输入#

有时,基础工具具有多个必须一起提供的参数(它们是相互依赖的)或多个不能一起提供的参数(它们是互斥的)。 您可以使用记录类型或共用体 (union) 类型将参数加以组合,以分别描述这两种情况。

record.cwl#
#!/usr/bin/env cwl-runner
cwlVersion: v1.2
class: CommandLineTool
inputs:
  dependent_parameters:
    type:
      type: record
      name: dependent_parameters
      fields:
        itemA:
          type: string
          inputBinding:
            prefix: -A
        itemB:
          type: string
          inputBinding:
            prefix: -B
  exclusive_parameters:
    type:
      - type: record
        name: itemC
        fields:
          itemC:
            type: string
            inputBinding:
              prefix: -C
      - type: record
        name: itemD
        fields:
          itemD:
            type: string
            inputBinding:
              prefix: -D
outputs:
  example_out:
    type: stdout
stdout: output.txt
baseCommand: echo
record-job1.yml#
dependent_parameters:
  itemA: one
exclusive_parameters:
  itemC: three
$ cwltool record.cwl record-job1.yml
INFO /home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/envs/latest/bin/cwltool 3.2.20260411152607
INFO Resolved 'record.cwl' to 'file:///home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/checkouts/latest/src/_includes/cwl/inputs/record.cwl'
ERROR Workflow error, try again with --debug for more information:
Invalid job input record:
record-job1.yml:1:1: the 'dependent_parameters' field is not valid because
                       missing required field 'itemB'

在第一个示例中,一旦提供 itemA 就必须同时提供 itemB.

record-job2.yml#
dependent_parameters:
  itemA: one
  itemB: two
exclusive_parameters:
  itemC: three
  itemD: four
$ cwltool record.cwl record-job2.yml
INFO /home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/envs/latest/bin/cwltool 3.2.20260411152607
INFO Resolved 'record.cwl' to 'file:///home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/checkouts/latest/src/_includes/cwl/inputs/record.cwl'
WARNING record-job2.yml:6:3: Warning: invalid field 'itemD', expected one of: 'itemC'
INFO [job record.cwl] /tmp/zq4urrlh$ echo \
    -A \
    one \
    -B \
    two \
    -C \
    three > /tmp/zq4urrlh/output.txt
INFO [job record.cwl] completed success
{
    "example_out": {
        "location": "file:///home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/checkouts/latest/src/_includes/cwl/inputs/output.txt",
        "basename": "output.txt",
        "class": "File",
        "checksum": "sha1$329fe3b598fed0dfd40f511522eaf386edb2d077",
        "size": 23,
        "path": "/home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/checkouts/latest/src/_includes/cwl/inputs/output.txt"
    }
}INFO Final process status is success
$ cat output.txt
-A one -B two -C three

在第二个示例中,itemCitemD 是互斥的。因此,只有第一个匹配项 (itemC) 会添加到命令行,而余下的 (itemD) 将被忽略。

record-job3.yml#
dependent_parameters:
  itemA: one
  itemB: two
exclusive_parameters:
  itemD: four
$ cwltool record.cwl record-job3.yml
INFO /home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/envs/latest/bin/cwltool 3.2.20260411152607
INFO Resolved 'record.cwl' to 'file:///home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/checkouts/latest/src/_includes/cwl/inputs/record.cwl'
INFO [job record.cwl] /tmp/thtn7i__$ echo \
    -A \
    one \
    -B \
    two \
    -D \
    four > /tmp/thtn7i__/output.txt
INFO [job record.cwl] completed success
{
    "example_out": {
        "location": "file:///home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/checkouts/latest/src/_includes/cwl/inputs/output.txt",
        "basename": "output.txt",
        "class": "File",
        "checksum": "sha1$77f572b28e441240a5e30eb14f1d300bcc13a3b4",
        "size": 22,
        "path": "/home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/checkouts/latest/src/_includes/cwl/inputs/output.txt"
    }
}INFO Final process status is success
$ cat output.txt
-A one -B two -D four

在第三个示例中,仅提供了 itemD, 因此它出现在命令行上。

2.4.3.1. 互斥输入参数与表达式#

将互斥的输入参数与表达式结合使用时,需要注意 inputs 这个 JavaScript 对象可能包含互斥输入值中的任何一个。因为这些互斥值可能属于不同类型,您可能需要在引用 input 对象的属性时检查实际出现的是哪一类型。

我们来看一个例子,其中 file_format 输入参数的取值是互斥的。该参数接受 null(即未提供任何值),或一个特定的枚举类型所包括的值。

exclusive-parameter-expressions.cwl#
cwlVersion: v1.2
class: CommandLineTool

inputs:
  file_format:
    type:
      - 'null'
      - name: format_choices
        type: enum
        symbols:
          - auto
          - fasta
          - fastq
          - fasta.gz
          - fastq.gz
        inputBinding:
          position: 0
          prefix: '--format'
outputs:
  text_output:
    type: string
    outputBinding:
      outputEval: $(inputs.file_format)

baseCommand: 'true'

请注意,这里的 JavaScript 表达式用到了互斥输入参数的值,但没有考虑到出现空值 null 的情况。如果提供的值有效,比如 fasta(枚举中的一个值),命令将会成功执行:

$ cwltool exclusive-parameter-expressions.cwl --file_format fasta
INFO /home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/envs/latest/bin/cwltool 3.2.20260411152607
INFO Resolved 'exclusive-parameter-expressions.cwl' to 'file:///home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/checkouts/latest/src/_includes/cwl/inputs/exclusive-parameter-expressions.cwl'
INFO [job exclusive-parameter-expressions.cwl] /tmp/_wp76xdf$ true \
    --format \
    fasta
INFO [job exclusive-parameter-expressions.cwl] completed success
{
    "text_output": "fasta"
}INFO Final process status is success

但是,如果未提供任何输入值,则 file_format 的值为 null, 从而不符合输出字段的预期类型(字符串 string),导致工作流运行失败。

$ cwltool exclusive-parameter-expressions.cwl
INFO /home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/envs/latest/bin/cwltool 3.2.20260411152607
INFO Resolved 'exclusive-parameter-expressions.cwl' to 'file:///home/docs/checkouts/readthedocs.org/user_builds/common-workflow-languageuser-guide-zh-hans/checkouts/latest/src/_includes/cwl/inputs/exclusive-parameter-expressions.cwl'
INFO [job exclusive-parameter-expressions.cwl] /tmp/f3bwbahu$ true
ERROR [job exclusive-parameter-expressions.cwl] Job error:
Error validating output record. the 'text_output' field is not valid because
  the value is not string
 in {
    "text_output": null
}
WARNING [job exclusive-parameter-expressions.cwl] completed permanentFail
{}WARNING Final process status is permanentFail

为了修正这个问题,需要专门处理出现 null 空值的情形。例如,表达式可以修改为 $(inputs.file_format || 'auto'), 从而在命令行或作业输入文件未提供值的情况下有默认值 "auto" 可用。

这里,我们要使用的是 JavaScript 中布尔“或”运算符 || 的“短路”特点。如果 inputs.file_format 为布尔意义上的“真值”(例如来自枚举的有效、非空字符串),这个表达式的计值过程到 || 运算符前的操作数就终止,也就是“短路”了。反之,如果 inputs.file_formatnull, 则该表达式整体的值就等于后一个操作数,因此这里可以用来安放合理的默认值。