我有一个 Snakemake 工作流程,其中一条规则似乎随机失败。我正在使用 Snakemake 7.7.0 并使用
retries
指令为规则设置重试。该命令打印到 stdout 和 stderr,我想将两者附加到日志文件,保留失败尝试的输出,以便我可以跟踪失败。我所拥有的简化版本如下:
rule flaky_rule:
input:
infile = "{sample}/foo.txt"
output:
outfile = "{sample}/bar.txt"
retries: 3
log:
flaky_rule_log = "{sample}/logs/flaky_rule.log"
shell:
"""
flaky_script -i "{input.infile}" -o "{output.outfile}" >> "{log.flaky_rule_log}" 2>&1
"""
但是,当我运行它并且规则失败并重新运行时,日志文件似乎被覆盖了。目前,我的解决方法是改为在
params
指令中设置日志文件,但这当然会让我被 linter 告知,因为我“没有设置日志文件”并且对我来说有点老套。有没有更惯用的方法来做到这一点(在这个版本或更高版本中)?
可能太复杂而且不是很惯用,但无论如何这里有一个选项。将您的命令作为 python 子进程运行,分析输出并在多次重试后决定要做什么。例如:
rule flaky_rule:
input:
infile = "{sample}/foo.txt"
output:
outfile = "{sample}/bar.txt"
params:
retries = 3
log:
flaky_rule_log = "{sample}/logs/flaky_rule.log"
run:
import subprocess
for retry in range(0, params.retries):
p = subprocess.Popen('flacky_script {input} {output} >> "{log.flaky_rule_log}" 2>&1',
stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
stdout, stderr = p.communicate()
if p.returncode == 0:
break
if p.returncode != 0:
raise Exception('Failed after %s retries' % params.retries)
这是基于对相关问题的回答的变体。这个想法是将日志文件的路径指定为资源。这意味着
snakemake
不会自动清除它(在某些情况下这可能是不可取的,因此请谨慎使用):
rule flaky_rule:
input:
infile = "{sample}/foo.txt"
output:
outfile = "{sample}/bar.txt"
resources:
flaky_rule_log = lambda wildcards, attempt: f"{wildcards.sample}/logs/flaky_rule_attempt{attempt}.log"
retries: 3
shell:
"""
flaky_script -i "{input.infile}" -o "{output.outfile}" >> "{resources.flaky_rule_log}" 2>&1
"""
如果
params
或logs
支持attempt
就好了,但现在这仍然是一个悬而未决的问题.