Snakemake允许使用log
参数为每个规则创建日志,该参数指定日志文件的名称。将结果从shell
输出到此日志是相对简单的,但是我无法找出一种记录run
输出(即python脚本)输出的方法。
一种解决方法是将python代码保存在脚本中,然后从shell运行它,但是我想知道是否还有另一种方法?
答案 0 :(得分:1)
我有一些同时使用log
和run
指令的规则。在run
指令中,我“手动”打开并写入日志文件。
例如:
rule compute_RPM:
input:
counts_table = source_small_RNA_counts,
summary_table = rules.gather_read_counts_summaries.output.summary_table,
tags_table = rules.associate_small_type.output.tags_table,
output:
RPM_table = OPJ(
annot_counts_dir,
"all_{mapped_type}_on_%s" % genome, "{small_type}_RPM.txt"),
log:
log = OPJ(log_dir, "compute_RPM_{mapped_type}", "{small_type}.log"),
benchmark:
OPJ(log_dir, "compute_RPM_{mapped_type}", "{small_type}_benchmark.txt"),
run:
with open(log.log, "w") as logfile:
logfile.write(f"Reading column counts from {input.counts_table}\n")
counts_data = pd.read_table(
input.counts_table,
index_col="gene")
logfile.write(f"Reading number of non-structural mappers from {input.summary_table}\n")
norm = pd.read_table(input.summary_table, index_col=0).loc["non_structural"]
logfile.write(str(norm))
logfile.write("Computing counts per million non-structural mappers\n")
RPM = 1000000 * counts_data / norm
add_tags_column(RPM, input.tags_table, "small_type").to_csv(output.RPM_table, sep="\t")
对于写入stdout的第三方代码,也许redirect_stdout
上下文管理器可能会有所帮助(在https://stackoverflow.com/a/40417352/1878788中找到,请参见
https://docs.python.org/3/library/contextlib.html#contextlib.redirect_stdout。
测试snakefile,test_run_log.snakefile
:
from contextlib import redirect_stdout
rule all:
input:
"test_run_log.txt"
rule test_run_log:
output:
"test_run_log.txt"
log:
"test_run_log.log"
run:
with open(log[0], "w") as log_file:
with redirect_stdout(log_file):
print(f"Writing result to {output[0]}")
with open(output[0], "w") as out_file:
out_file.write("result\n")
运行它:
$ snakemake -s test_run_log.snakefile
结果:
$ cat test_run_log.log
Writing result to test_run_log.txt
$ cat test_run_log.txt
result
答案 1 :(得分:1)
我的解决方法如下。这对于常规日志和带回溯的日志记录异常都非常有用。然后,您可以将记录器设置包装到一个函数中,以使其更有条理。虽然不是很漂亮。如果snakemake能够自己做到,那就更好了。
import logging
# some stuff
rule logging_test:
input: 'input.json'
output: 'output.json'
log: 'rules_logs/logging_test.log'
run:
logger = logging.getLogger('logging_test')
fh = logging.FileHandler(str(log))
fh.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
logger.addHandler(fh)
try:
logger.info('Starting operation!')
# do something
with open(str(output), 'w') as f:
f.write('success!')
logger.info('Ended!')
except Exception as e:
logger.error(e, exc_info=True)