pythonforbio.
[WASM idle]
Biopython09/15

Biopython Deprecations

Starting sandbox…
Beginnerlesson

Biopython Deprecations

In one line: Biopython removes things aggressively, and the removals invalidate most tutorials written before 2026 — this is the lookup table.

The removal table

Removed Deprecated Removed in Replacement
Bio.Alphabet 1.74 1.78 nothing — sequences are just letters
Bio.SubsMat 1.78 1.80 Bio.Align.substitution_matrices
Seq.tomutable(), Seq.toseq() 1.79 1.81 MutableSeq() / Seq() constructors
Seq.ungap() 1.80 1.82 seq.replace("-", "")
Bio.SeqUtils.GC() 1.80 1.82 gc_fraction()note the 100× scale change
Bio.SeqUtils.CodonUsage funcs 1.80 1.82 CodonAdaptationIndex class
Bio.Blast.ParseBlastTable 1.80 1.82 Bio.Align.parse()
Bio.Application 1.82 1.86 subprocess
Bio.Blast.Applications 1.82 1.86 subprocess
Bio.Align.Applications 1.82 1.86 subprocess
Bio.Phylo.Applications 1.82 1.86 subprocess
Bio.pairwise2 1.80 not yet Bio.Align.PairwiseAligner

The three bolded rows are the ones that break the most existing code.

1. Bio.Alphabet — removed 1.78

# OLD — ImportError
from Bio.Alphabet import IUPAC, generic_dna
Seq("ATGGCC", IUPAC.unambiguous_dna)

# NEW
Seq("ATGGCC")
record.annotations["molecule_type"] = "DNA"     # only where a format needs it

The alphabet system tried to make Biopython type-check biology and mostly produced confusing errors instead. It is gone entirely; a Seq is letters, and you know what they mean.

The only place molecule type still matters is writing formats that record it (GenBank, EMBL), where it lives in record.annotations.

2. Bio.Application — removed 1.86

This is the biggest one. Every command-line wrapper is gone.

# OLD — ImportError in 1.86+
from Bio.Blast.Applications import NcbiblastnCommandline
from Bio.Align.Applications import MuscleCommandline, MafftCommandline, ClustalOmegaCommandline

cline = NcbiblastnCommandline(query="q.fa", db="nt", out="r.xml", outfmt=5)
stdout, stderr = cline()
# NEW
import subprocess

subprocess.run([
    "blastn", "-query", "q.fa", "-db", "nt", "-out", "r.xml", "-outfmt", "5",
], check=True)

with open("aligned.fasta", "w") as fh:
    subprocess.run(["mafft", "--auto", "input.fasta"], stdout=fh, check=True)

check=True is essential. The old wrappers raised ApplicationError on failure; subprocess.run without check=True returns silently, and you go on to parse an empty output file — which looks like "no hits" rather than "the tool crashed".

A reusable wrapper:

import subprocess, shutil

def run_tool(cmd, stdout_path=None, **kw):
    if shutil.which(cmd[0]) is None:
        raise FileNotFoundError(f"{cmd[0]} not on PATH")
    if stdout_path:
        with open(stdout_path, "w") as fh:
            return subprocess.run(cmd, stdout=fh, stderr=subprocess.PIPE,
                                  text=True, check=True, **kw)
    return subprocess.run(cmd, capture_output=True, text=True, check=True, **kw)

The shutil.which check turns a cryptic FileNotFoundError deep in subprocess into a clear message.

3. GC() → gc_fraction() — the silent 100× bug

from Bio.SeqUtils import GC                      # ImportError (removed 1.82)
GC(seq)                                           # returned 41.5  (percent)

from Bio.SeqUtils import gc_fraction
gc_fraction(seq)                                  # returns 0.415  (fraction)

A naive substitution changes every GC threshold in your code by a factor of 100. if gc > 60 becomes always-false. This one deserves a grep of your codebase, not just a find-and-replace.

4. Bio.SubsMat → Bio.Align.substitution_matrices

# OLD
from Bio.SubsMat import MatrixInfo
MatrixInfo.blosum62[("A", "W")]      # dict; only one triangle populated!

# NEW
from Bio.Align import substitution_matrices
m = substitution_matrices.load("BLOSUM62")
m["A", "W"]; m["W", "A"]              # symmetric, array-backed

The old one being half-populated meant every user wrote a try/except KeyError to swap the tuple. The new one just works. See Substitution Matrices.

5. pairwise2 → PairwiseAligner

Deprecated since 1.80, still present, slated for removal.

# OLD
from Bio import pairwise2
pairwise2.align.globalms(a, b, 2, -1, -10, -0.5)

# NEW
from Bio import Align
aligner = Align.PairwiseAligner(match_score=2, mismatch_score=-1,
                                open_gap_score=-10, extend_gap_score=-0.5)
aligner.align(a, b)

See PairwiseAligner.

Auditing existing code

grep -rn "Bio.Alphabet\|IUPAC\|generic_dna\|generic_protein" .
grep -rn "Applications\|Commandline" .
grep -rn "SubsMat\|MatrixInfo" .
grep -rn "SeqUtils import GC\b\|SeqUtils.GC(" .
grep -rn "pairwise2" .
grep -rn "\.ungap(\|\.tomutable(\|\.toseq(" .

Behaviour changes that are not removals

These do not error — they silently change results, which is worse:

  • 1.86: PairwiseAligner default gap scores changed to reduce redundant co-optimal alignments. Your chosen alignment may differ. Set gap scores explicitly.
  • 1.86: PDBIO enforces the wwPDB B-factor field width (max 6 characters). Custom B-factor values (conservation scores, pLDDT) outside the legal range now raise instead of writing a malformed file.
  • 1.85: Bio.SeqIO parsing performance improvements — faster, same output.
  • 1.87: CVE-2025-68463 fixed in Bio.Entrez.Parser. A security fix; upgrade if you parse XML from untrusted sources.

Why the churn

Biopython has a published deprecation policy: declare obsolete → deprecate with a warning for at least one release → remove. The pace picked up because the project is shedding two decades of accumulated surface area — the command-line wrappers in particular were an enormous maintenance burden that duplicated what subprocess does better.

The practical consequence for you: pin your Biopython version in any pipeline, and read NEWS.rst before upgrading.

biopython>=1.86,<2

Version support

Biopython Python
1.87 (Mar 2026) 3.10–3.14
1.86 (Oct 2025) 3.10–3.14
1.85 3.9–3.13 (3.9 deprecated)

Common mistakes

  • Following a pre-2026 tutorial and hitting a wall of ImportErrors.
  • Substituting gc_fraction for GC without fixing thresholds.
  • subprocess.run without check=True.
  • Not pinning Biopython in a pipeline.
  • Assuming a warning-free upgrade means no behaviour change. The alignment and B-factor changes are silent.
  • Copying Stack Overflow answers without checking their date.

See also

Biopython · Versions and Compatibility · PairwiseAligner · Substitution Matrices · Bio.Blast · Bio.SeqUtils · Applied - Reproducible Environment

scratch

No output yet — run the code to populate this drawer.