I have a snakemake rule that generates symbolic links in a target folder. This is done within a Python script and the script
directive in the rule. This rule is always rerun with reason: Code has changed since last execution
, even though I didn’t change any code (rerunning the same snakemake
command twice will rerun the rule).
Interestingly, when implementing the symbolic link using bash in the shell
directive, or even the exact same Python code in the run
directive, the rule is not rerun (expected behaviour).
Any idea how to fix this? Is this a bug or am I missing something here? I’m using absolute paths in the symbolic links and they are detected correctly by snakemake.
Here is a minimal example:
Folder structure after running snakemake (which generates resources
and results
)
.
├── Snakefile
├── link_file.py
├── resources
│ └── A.txt
└── results
└── A.txt -> /absolute/path/to/resources/A.txt
Snakefile
import os
from pathlib import Path
# Rule to generate the symbolic link
rule:
input:
"results/A.txt"
# Rule to create some resource to start with
rule create_resource:
output:
"resources/{sample}.txt"
shell:
"echo {wildcards.sample} > {output}"
rule link_file:
input:
source="resources/{sample}.txt"
output:
link="results/{sample}.txt"
script:
"link_file.py"
#shell:
# "ln -s $(realpath {input.source}) $(realpath {output.link})"
#run:
# os.symlink(Path(input.source).resolve(), Path(output.link).resolve())
When using the script
directive, the rule is rerun. When using the commented out shell
or run
directive, the rule is not rerun.
link_file.py
import os
from pathlib import Path
def link_data(
source: str, link: str
) -> None:
os.symlink(Path(source).resolve(), Path(link).resolve())
link_data(
snakemake.input.source, snakemake.output.link
)
I tried this with snakemake 8.16.0
(current latest stable version) and 8.13.0
.
EDIT: I wanted to check what code changed, but unfortunately running snakemake --list-changes code
fails currently, see this issue I opened.