In Colab every file lands in the same place, on a machine you never see. On your own laptop nothing lands anywhere predictable — and today you have 99 files to find.
Your download went somewhere. Not the same somewhere as the person next to you — different username, different folder, and on Windows a \ instead of a /.
That is the entire reason Python has Path objects instead of just gluing strings together.
Open a terminal now — in VS Code it is ⌃` — and use those three commands to find the folder you unzipped.
Everything you just did by hand, pathlib does in code. Same ideas, same order — you already know what these mean.
One import gets you all of it: from pathlib import Path
Once it is a Path, you can ask it questions — and it answers the same way on every operating system.
from pathlib import Path
data_dir = Path("/Users/you/Downloads/sequences")
bee = data_dir / "Bombus_terrestris.fasta"
bee.name # 'Bombus_terrestris.fasta'
bee.stem # 'Bombus_terrestris' <- the species, free
bee.suffix # '.fasta'
bee.exists() # True — or a problem you can catch earlydata_dir / "file.fasta" reads like a path and behaves like one. Python inserts the right separator, so the same code works on macOS and Windows.
Your 99 files are named Genus_species.fasta. That means .stem hands you the species name without a single line of string parsing — the filename is data.
Every file you open has to be closed again. Forget, and your results can sit in a buffer and never reach the disk. with closes it for you — including when your code crashes half way through.
with open(bee) as f:
text = f.read()
# ...and the file is closed here,
# even if something went wrong above.with open(out_file, "w") as f:
f.write("species,dna,protein\n")
for name, d, p in rows:
f.write(f"{name},{d},{p}\n")⚠ "w" empties the file first, without asking. Use "a" to add to the end instead.
💡 For a whole small file in one go, Path has shortcuts: p.read_text() and p.write_text(s).
Your script works. You run it from one folder up, and it cannot find anything. Nothing changed in the code — you did.
The folder your terminal was in when you pressed Enter. Move, and it is a different answer.
The folder the script is saved in. Same answer from anywhere — this is the one you usually want.
# where you happen to be standing — this MOVES Path.cwd() # where this script lives — this does not Path(__file__).parent results_dir = Path(__file__).parent / "results" results_dir.mkdir(parents=True, exist_ok=True)
exist_ok=True means running it a second time is not an error — and you will run it a second time.
The biology is already written — the codon table, translate(), the comparison. You are not here to do genetics today. You are here to point a program at a folder.
Read 99 sequences from sequences/ Wrote 98 rows to .../results/drift.csv species DNA protein silent Bombus_cryptarum 36 1 35 Bombus_lucorum 43 2 41 Bombus_ignitus 48 5 43 Nomioides_minutissimus 152 61 91 Ceylalictus_variegatus 156 58 98 Andrena_agilissima 173 53 120
Thirty-six differences in the DNA. One in the protein. The gene drifts; the enzyme it builds barely moves — because natural selection can only see the protein.
Everyone's first run fails, and everyone's fails differently — that is TODO 1 doing its job.