如何解决如何访问snakemake python代码中的重试尝试?
当您使用--restart-times >= 1 执行snakemake 脚本时,它将尝试重新执行失败的运行。重新执行时,可以通过“资源”中的 lambda 函数访问执行尝试的次数。但是,我想访问我的规则之外的 Python 代码块中的尝试次数。我试图将尝试变量从资源块传递给我的 python 函数,但无济于事。我的snakemake 版本是5.32.1 和6.0.3 的快速测试看起来非常相似。
def getTargetFiles(files,attempted):
do stuff
return modified-target-files
rule do_things_rule:
input:
...
output:
getTargetFiles("file/path.txt",resources.attempt)
resources:
attempt=lambda wildcards,attempt: attempt,
不幸的是,这会产生错误。 “xxxx.py 第 172 行中的 NameError:未定义名称 'resources'”
我最接近的是访问“workflow.attempt”,但这似乎总是设置为 1。也许这是尝试的默认值?
rule do_things_rule:
input:
...
output:
getTargetFiles("file/path.txt",workflow.attempt)
我正在查看 snakemake 的内部结构,希望能找到解决方案。不幸的是,我的 Python 知识无法胜任这项任务。有一些变量可以代替workflow.attempt 访问,它们没有整数值。不确定是否有办法使用这些略有不同的方法来获取当前的尝试次数:
print snakemake.jobs.Job.attempt
<property object at 0x7f4eecba66d0>
print snakemake.jobs.Job._attempt
<member '_attempt' of 'Job' objects>
解决方法
这是一个最小的工作示例,我可以用它来重现您的错误。
DECLARE @DR DATETIME
DECLARE @SM INTEGER
SET @SM=5
SET @DR=getdate()
SELECT T.* FROM (SELECT A.IDT_APPEL AS NOTICKET,DEBUT.C_ACTION AS C_DEBUT,FIN.C_ACTION AS C_FIN,RS.DF_SEM AS F_TEST,RS.NUM_SEMAINE AS NUM_SEMAINE,E.L_EQUIPE AS EQUIPETICKET,EP.L_EQUIPE AS EQUIPESUP,A.C_UTIL_INT,CONCAT(util.N_UTIL,' ',util.PRE_UTIL) AS INTERVENANT,CASE
WHEN Datepart(ISO_WEEK,FIN.D_CREATION) = RS.NUM_SEMAINE
AND Datediff(DAY,FIN.D_CREATION,RS.DF_SEM) < 7
AND FIN.C_TACTION = 'SYS_EQUIPE'
AND Isnull(UTIL.C_ISIPARC,'0') <> '666' THEN 1
ELSE 0
END AS COND_TR,'0') = '666' THEN 1
ELSE 0
END AS COND_REJ,CASE
WHEN FIN.C_TACTION IN('SYS_CLOS_TECH','SYS_CLOS')
AND Datepart(ISO_WEEK,RS.DF_SEM) < 7 THEN 1
ELSE 0
END AS COND_CLOS,DEBUT.D_CREATION) = RS.NUM_SEMAINE
AND Datediff(DAY,DEBUT.D_CREATION,RS.DF_SEM) < 7 THEN 1
ELSE 0
END AS NB_TICKET_ENTRE,CASE
WHEN ( ( FIN.D_CREATION IS NULL
OR FIN.D_CREATION > RS.DF_SEM )
AND DEBUT.D_CREATION < RS.DF_SEM ) THEN ( CASE
WHEN Datediff(DAY,RS.DF_SEM) - 2 < 5 THEN '05'
WHEN Datediff(DAY,RS.DF_SEM) - 2 >= 5
AND Datediff(DAY,RS.DF_SEM) - 2 < 10 THEN '10'
WHEN Datediff(DAY,RS.DF_SEM) - 2 >= 10
AND Datediff(MONTH,RS.DF_SEM) < 1 THEN '30'
WHEN Datediff(MONTH,RS.DF_SEM) >= 1 THEN '30+'
ELSE NULL
END )
ELSE NULL
END AS F_NONCLOS,RS.DF_SEM) < 7 THEN ( CASE
WHEN Datediff(DAY,FIN.D_CREATION) < 1 THEN '01'
WHEN Datediff(DAY,FIN.D_CREATION) >= 1
AND Datediff(DAY,FIN.D_CREATION) < 2 THEN '02'
WHEN Datediff(DAY,FIN.D_CREATION) >= 2
AND Datediff(DAY,FIN.D_CREATION) < 5 THEN '05'
WHEN Datediff(DAY,FIN.D_CREATION) >= 5
AND Datediff(DAY,FIN.D_CREATION) < 15 THEN '15'
WHEN Datediff(DAY,FIN.D_CREATION) >= 15 THEN '15+'
ELSE NULL
END )
ELSE NULL
END AS F_CLOS,DEBUT.D_CREATION AS DEBUT,FIN.D_CREATION AS FIN,RS.YEAR AS YEARS
FROM APPEL A
INNER JOIN (SELECT B.NO_APPEL,B.C_ACTION,B.D_CREATION,B.C_EQUIPE,B.C_TACTION,Lead(B.C_ACTION,1)
OVER (
PARTITION BY B.NO_APPEL
ORDER BY B.C_ACTION) AS FIN_C_ACTION
FROM ACTIONS B WITH (NOLOCK)
WHERE B.C_TACTION IN ( 'SYS_EQUIPE','SYS_CLOS_TECH','SYS_REOUVERT','SYS_CLOS' )
AND ( CAST(B.D_CREATION AS DATE)< Dateadd(week,Datediff(week,Dateadd(WEEK,@DR)),0) )) DEBUT
ON ( A.NO_APPEL = DEBUT.NO_APPEL
AND DEBUT.C_EQUIPE IN('ETUD_MET_BILIZI')
AND DEBUT.C_TACTION IN( 'SYS_EQUIPE','SYS_REOUVERT' ) )
LEFT JOIN ACTIONS FIN WITH (NOLOCK)
ON ( FIN.C_ACTION = DEBUT.FIN_C_ACTION )
LEFT JOIN UTILISATEUR UTIL WITH (NOLOCK)
ON ( UTIL.C_UTIL = FIN.C_UTIL )
INNER JOIN EQUIPE E WITH (NOLOCK)
ON DEBUT.C_EQUIPE = E.C_EQUIPE
INNER JOIN EQUIPE EP WITH (NOLOCK)
ON E.C_EQUIPE_PERE = EP.C_EQUIPE
INNER JOIN (SELECT DISTINCT Datepart(ISO_WEEK,P.D_JOUR) AS Num_semaine,Dateadd(SECOND,59,Dateadd(MINUTE,Dateadd(HOUR,23,Dateadd(DAY,-1,Dateadd(week,P.D_JOUR) + 1,0))))) AS DF_SEM,YEAR(P.D_JOUR) AS YEAR
FROM PLANNINGS P WITH (NOLOCK)
INNER JOIN TCALEND TC WITH (NOLOCK)
ON TC.C_TCALEND = P.C_TCALEND
AND TC.F_TCALENDSTD = 1
WHERE ( C_TPERIOD <> 3
AND C_TPERIOD <> 9 )) RS
ON ( ( FIN.D_CREATION > Dateadd(DAY,-7,RS.DF_SEM)
OR FIN.D_CREATION IS NULL )
AND (CAST( RS.DF_SEM AS DATE) >= Dateadd(week,- @SM,0)
AND CAST(RS.DF_SEM AS DATE) <= Dateadd(week,0) ) )
WHERE (A.C_NATURE = 'INC' OR A.C_NATURE = 'DMD')
AND ( A.D_CLOTTECH >= Dateadd(week,0)
OR A.D_CLOTTECH IS NULL )
UNION
SELECT DISTINCT NULL IDT_APPEL,NULL C_DEBUT,NULL C_FIN,Datepart(ISO_WEEK,NULL EQUIPETICKET,NULL EQUIPESUP,NULL C_UTIL_INT,NULL INTERVENANT,0 COND_TR,0 COND_REJ,0 COND_CLOS,0 NB_TICKET_ENTRE,NULL F_NONCLOS,NULL F_CLOS,NULL,--YEAR(P.D_JOUR) AS YEARS
case when Datepart(ISO_WEEK,P.D_JOUR)=1 then YEAR(getdate()) ELSE YEAR(P.D_JOUR) end AS YEARS
FROM PLANNINGS P WITH (NOLOCK)
INNER JOIN TCALEND TC WITH (NOLOCK)
ON TC.C_TCALEND = P.C_TCALEND
AND TC.F_TCALENDSTD = 1
WHERE ( C_TPERIOD <> 3
AND C_TPERIOD <> 9 )
AND Dateadd(SECOND,0))))) >= Dateadd(week,0)
AND Dateadd(SECOND,0))))) <= Dateadd(week,0)) T ORDER BY T.YEARS ASC
确实,def getTargetFiles(files,attempted):
return f"{files[:-4]}-{attempted}.txt"
rule do_things_rule:
resources:
nr = lambda wildcards,attempt: attempt
output:
getTargetFiles("test.txt",resources.nr)
shell:
'echo "Failing on purpose to produce file'
'{output} at attempt {resources.nr}'
'"; exit 1 '
不知道 output
。我认为这是因为它
需要在规则运行之前访问(见下文)。相反,如果你
用 resources
替换 getTargetFiles("test.txt",resources.nr)
,然后规则运行正确数量的
次并且 shell 命令可以访问 getTargetFiles("test.txt",1)
。
据我所知,这个问题有一个根本原因。
snakemake 工作流是“根据规则定义的,这些规则定义了如何 从输入文件创建输出文件。规则之间的依赖是 自动确定”。(引自Tutorial)这意味着snakemake需要知道该规则将创建哪个输出文件。然后,它将确定是否需要运行该规则。因此, 尝试至少通常不应该是输出文件名的一部分。
也许您想合并失败尝试的不同文件?但是,如果规则失败,则不会有输出文件。就算你强求。该文件将被snakemake删除。 (见下例)
resources.nr
如何不考虑文件名中的尝试次数,而是在 shell 命令中使用 def getTargetFiles(files,attempted):
return f"{files[:-4]}-{attempted}.txt"
rule combine:
input:
'test-1.txt'
output:
'test-combined.txt'
shell:
'cat test-[0-9]*.txt > test-combined.txt'
rule do_things_rule:
resources:
nr = lambda wildcards,1)
shell:
'touch {output}; '
'echo "Failing on purpose to produce file'
'{output} at attempt {resources.nr}'
'"; exit 1 '
?
希望这能解决您的问题。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。