Snakemake表示,即使代码段未被访问,列表索引也超出了范围



我今天发生了一个奇怪的错误,我可以用下面的例子重现它:

files = ["A.txt", "B.txt"]

rule all:
input: "copied_joined.txt"
rule A:
input: files
output: "joined.txt"
shell: "cat {input} >> {output}"

rule B:
input:
data=rules.A.output
output: "copied_joined.txt"
shell:
"""
if [[ {input} == "joined.txt" ]]; then
echo "Running on {input}!"
cp {input.data[0]} {output}
elif {input} == "garbage_string" ]]; then
echo "Running on garbage!"
cp {input.data[1]} {output}
fi
"""

rule B中,从未到达elif部分,但Snakemake仍然显示错误IndexError: list index out of range,因为我正在访问不存在的input.data[1]

在我的特定用例中,我使用的是一个输入函数,它将提供一个或两个基于通配符的文件。然后,我对文件执行特定的操作,类似于上面的if/elif,这会导致Snakemake失败。删除cp {input.data[1]} {output}解决问题

为了解决我自己的问题,如果我最初要返回一个文件,我返回了同一文件的两个副本,例如:

def input_data(wildcards):
if something_true:
file_one = "ONE.txt"
return "ONE.txt", "TWO.txt"
else:
return "THREE.txt", "THREE.txt" 

我的破解解决方案有效,但我想知道是否有更棘手的解决方案?

谢谢你的帮助!!

我已经通过从input中移除括号[]解决了我的解决方案。新代码如下:

files = ["A.txt", "B.txt"]

rule all:
input: "copied_joined.txt"
rule A:
input: files
output: "joined.txt"
shell: "cat {input} >> {output}"

rule B:
input:
data=rules.A.output
output: "copied_joined.txt"
shell:
"""
if [[ {input} == "joined.txt" ]]; then
echo "Running on {input}!"
cp {input.data} {output}
elif {input} == "garbage_string" ]]; then
echo "Running on garbage!"
cp {input.data} {output}
fi
"""

这可能不适用于cp命令,但总体要点是相同的。

在python中处理列表和if else可能比在bash中更容易。例如,您可以考虑以下内容(检查语法错误等):

rule B:
input:
data=rules.A.output
output: "copied_joined.txt"
run:
if len(input.data) == 1:
shell("cp {input.data[0]} {output}") # Or use only python code if you only need to copy files
elif len(input.data) == 2:
shell("cp {input.data[1]} {output}")
else:
sys.exit("This should not happen")

不相关,规则A中的此位:

shell: "cat {input} >> {output}"

请注意,snakemake在运行规则之前会删除{output},因此您不会像查看shell命令时所期望的那样,真正将{input}附加到{output}。如果你真的需要附加,也许可以单独发布一个问题。

最新更新