similar-rs
Rust-powered text diffing for Python: bindings to the
similar crate by Armin Ronacher.
It also ships a drop-in replacement for the standard library's difflib
that runs 2-4x faster
on real file diffs and ~200x on accurate whole-file similarity — on tiny
inputs it is a wash. It also adds six diff algorithms stdlib does not have.
Real CPython sources, one Apple M4 — per-pair tables in benchmarks/results.md.
Install
pip install similar-rs
Wheels: Linux (x86_64, aarch64), macOS (arm64, x86_64) and Windows (AMD64). They are abi3 — one wheel per platform, CPython 3.9+. No system dependencies. An sdist is published too; building from it needs a Rust toolchain.
Usage
import similar
print(similar.unified_diff("a\nb\n", "a\nc\n", header=("old", "new")))
TextDiff computes the diff once and exposes the opcodes and a similarity
ratio:
d = similar.TextDiff("a\nb\n", "a\nc\n", granularity="lines")
d.ops() # [("equal", (0, 1), (0, 1)), ("replace", (1, 2), (1, 2))]
d.ratio() # 0.5
granularity is lines, words or chars. algorithm is one of myers
(default), raw-myers, patience, lcs, hunt or histogram; both
TextDiff and unified_diff accept it.
difflib drop-in
Change one import line — SequenceMatcher, unified_diff and
get_close_matches then run on Rust:
from similar import difflib # instead of: import difflib
difflib.SequenceMatcher(None, "kitten", "sitting").ratio() # 0.6153...
"".join(difflib.unified_diff(["a\n", "b\n"], ["a\n", "c\n"], "old", "new"))
difflib compatibility
| API | Status |
|---|---|
SequenceMatcher.ratio, quick_ratio, real_quick_ratio |
Rust |
SequenceMatcher.get_opcodes, get_matching_blocks, get_grouped_opcodes |
Rust |
unified_diff, get_close_matches |
Rust |
Differ, HtmlDiff, ndiff, context_diff, restore, diff_bytes |
stdlib passthrough |
SequenceMatcher.find_longest_match |
stdlib passthrough |
Known differences:
isjunkandautojunkare ignored; passing anisjunkraises aRuntimeWarning.- Opcodes are a valid edit script, but not byte-for-byte the one stdlib
produces — it is a different algorithm, finding a different (as a rule, no
smaller) set of matches.
ratio()andget_opcodes()can therefore differ from stdlib's at eitherautojunksetting, not justautojunk=True. get_close_matchescan return a different set for the same reason: the underlying ratios differ. The tie order among equal ratios matches stdlib.find_longest_matchruns stdlib's algorithm withautojunk=False, so its result can differ from a default stdlib matcher's (autojunk=True) — and it may name a block thatget_matching_blocks()of the same object (Rust opcodes) does not contain.- Inputs must be
stror sequences ofstr. - The stdlib instance attributes
b2j,bjunk,bpopular,opcodesandmatching_blocksare absent; the caches are private. - Strings holding lone surrogates (as
diff_bytesproduces) cannot cross into Rust, so they take a slow pure-Python fallback via stdlibdifflib.
Limitations
No isjunk/autojunk, str only (no bytes), and no grapheme or
Unicode-word granularity yet. Open an issue if you need any of these.
Benchmarks
The same three workloads as the chart above, measured on real CPython sources (v3.9.0 vs v3.13.0 releases):
| workload | stdlib | similar-rs | speedup |
|---|---|---|---|
| two-line diff (call overhead) | 3.7 us | 2.9 us | 1.3x |
real file diff (argparse.py, 2,669 lines) |
3.7 ms | 0.9 ms | 4.0x |
accurate similarity of two ~35 KB files (autojunk=False) |
23.8 s | 120 ms | 198.1x |
Why the floor is a few times, not more: stdlib difflib is not naive — it
hashes lines once and diffs the hashes through C-backed dicts, so a Rust
port removes the interpreter, not the algorithm. Across five real file
pairs the win is 1.1-4.0x, growing with how much of the file changed.
Why the ceiling is ~200x: stdlib's autojunk heuristic trades accuracy
for speed, and on char-level input it discards most of the alphabet. Turn
it off for an accurate answer and stdlib exceeded a 30 s cap on four of
the five pairs, while similar-rs stays under 0.7 s. The heuristic also has
bad days of its own: on the difflib.py pair stdlib's default ran 712 ms
against our 3 ms. With autojunk on, the two libraries price the answer
differently — our default ratio is coarser than stdlib's on some inputs;
algorithm="raw-myers" returns a better match set than accurate stdlib at
a fraction of its cost.
Crossing into Rust costs a fixed ~2 us per call, which only shows on
inputs too small to contain work — that is the first row. For whole texts,
prefer the native entry point (similar.unified_diff): the line splitting
and formatting happen in Rust too.
When to use it:
| you are doing | what you get |
|---|---|
| diffs in a hot loop (services, CI, batch pipelines) | typically 2-4x for a one-line import change |
| accurate similarity of long texts (dedup, fuzzy matching) | the 200x class: feasible where stdlib times out |
git-style diffs (patience, histogram) |
algorithms stdlib does not have at any speed |
benchmarks/results.md
has the per-pair tables and the exact method; python benchmarks/bench.py
reproduces all of it, charts included. One machine, one benchmark — try it
on yours.
Contributing
Issues and PRs welcome. Build from a clone:
uv venv && uv pip install maturin pytest hypothesis
maturin develop
pytest
License
Apache-2.0 (see LICENSE). The difflib-compatible formatting code
in python/similar/difflib.py is derived from CPython's difflib and is
covered by the PSF License Version 2; see the notice at the end of
LICENSE. The wheel statically links the Rust crates it is built
from; their licenses are collected in
LICENSE-THIRD-PARTY, which ships inside the wheel.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file similar_rs-0.1.1.tar.gz.
File metadata
- Download URL: similar_rs-0.1.1.tar.gz
- Upload date:
- Size: 58.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8ebe07fb8b7de193cc731940d338b5965767871e1f8be127cd556c6ccb16953a
|
|
| MD5 |
4887a3ed4fc3fdcc3f76aa3f6ee17219
|
|
| BLAKE2b-256 |
e698cfe41a27789882c35383ee8558bcbdac32ab2ef11839ba117b096de350e0
|
Provenance
The following attestation bundles were made for similar_rs-0.1.1.tar.gz:
Publisher:
wheels.yml on Maksim-Burtsev/similar-rs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
similar_rs-0.1.1.tar.gz -
Subject digest:
8ebe07fb8b7de193cc731940d338b5965767871e1f8be127cd556c6ccb16953a - Sigstore transparency entry: 2627985615
- Sigstore integration time:
-
Permalink:
Maksim-Burtsev/similar-rs@61e7dea66fcba4140baf053a67cdacef9ec6474a -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Maksim-Burtsev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@61e7dea66fcba4140baf053a67cdacef9ec6474a -
Trigger Event:
push
-
Statement type:
File details
Details for the file similar_rs-0.1.1-cp39-abi3-win_amd64.whl.
File metadata
- Download URL: similar_rs-0.1.1-cp39-abi3-win_amd64.whl
- Upload date:
- Size: 557.2 kB
- Tags: CPython 3.9+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a4f217e18f15f7fc89b85499777597127f5ea01d3dc3a94fee926d86a04ff7fa
|
|
| MD5 |
8c52ecac3de25dd33b41fb37d7fa958b
|
|
| BLAKE2b-256 |
83322a14f142f7e0e2a6b951dc24da512b8e7bc094990bd05fc264c35d6b80b5
|
Provenance
The following attestation bundles were made for similar_rs-0.1.1-cp39-abi3-win_amd64.whl:
Publisher:
wheels.yml on Maksim-Burtsev/similar-rs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
similar_rs-0.1.1-cp39-abi3-win_amd64.whl -
Subject digest:
a4f217e18f15f7fc89b85499777597127f5ea01d3dc3a94fee926d86a04ff7fa - Sigstore transparency entry: 2627985735
- Sigstore integration time:
-
Permalink:
Maksim-Burtsev/similar-rs@61e7dea66fcba4140baf053a67cdacef9ec6474a -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Maksim-Burtsev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@61e7dea66fcba4140baf053a67cdacef9ec6474a -
Trigger Event:
push
-
Statement type:
File details
Details for the file similar_rs-0.1.1-cp39-abi3-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: similar_rs-0.1.1-cp39-abi3-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 703.3 kB
- Tags: CPython 3.9+, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6cb0b51e79d7bdabb6f20a0af971c0d3f47d7e0e5dc993eeb98e5ca321b1725c
|
|
| MD5 |
64ea0582b164b42cf1c7a975d2be12ba
|
|
| BLAKE2b-256 |
9ff245b6912a80e19d468d92bf9b93cbeaebf0f4e98583794e64cd90846db0a8
|
Provenance
The following attestation bundles were made for similar_rs-0.1.1-cp39-abi3-manylinux_2_28_x86_64.whl:
Publisher:
wheels.yml on Maksim-Burtsev/similar-rs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
similar_rs-0.1.1-cp39-abi3-manylinux_2_28_x86_64.whl -
Subject digest:
6cb0b51e79d7bdabb6f20a0af971c0d3f47d7e0e5dc993eeb98e5ca321b1725c - Sigstore transparency entry: 2627985638
- Sigstore integration time:
-
Permalink:
Maksim-Burtsev/similar-rs@61e7dea66fcba4140baf053a67cdacef9ec6474a -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Maksim-Burtsev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@61e7dea66fcba4140baf053a67cdacef9ec6474a -
Trigger Event:
push
-
Statement type:
File details
Details for the file similar_rs-0.1.1-cp39-abi3-manylinux_2_28_aarch64.whl.
File metadata
- Download URL: similar_rs-0.1.1-cp39-abi3-manylinux_2_28_aarch64.whl
- Upload date:
- Size: 650.2 kB
- Tags: CPython 3.9+, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6253fbcfed90df5492e97af0a48630911b714ca5acefdc29e72710d3fef7a4e0
|
|
| MD5 |
6da4b5a2086d33edda4c4dcc5b7795c3
|
|
| BLAKE2b-256 |
c85397ff2cd8d46af89b68276cad812574307096bd0fc5daee48e92c343ebd4b
|
Provenance
The following attestation bundles were made for similar_rs-0.1.1-cp39-abi3-manylinux_2_28_aarch64.whl:
Publisher:
wheels.yml on Maksim-Burtsev/similar-rs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
similar_rs-0.1.1-cp39-abi3-manylinux_2_28_aarch64.whl -
Subject digest:
6253fbcfed90df5492e97af0a48630911b714ca5acefdc29e72710d3fef7a4e0 - Sigstore transparency entry: 2627985654
- Sigstore integration time:
-
Permalink:
Maksim-Burtsev/similar-rs@61e7dea66fcba4140baf053a67cdacef9ec6474a -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Maksim-Burtsev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@61e7dea66fcba4140baf053a67cdacef9ec6474a -
Trigger Event:
push
-
Statement type:
File details
Details for the file similar_rs-0.1.1-cp39-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: similar_rs-0.1.1-cp39-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 621.5 kB
- Tags: CPython 3.9+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6ac5f3845931550f426cad8e0eda776ebd637866a4799f4b6c2543757298a6dc
|
|
| MD5 |
a14bcdb2f3727eaa61cf7c83582984bd
|
|
| BLAKE2b-256 |
821dc16887a3e6ebcdfe216b4c952e440075ef55040f55334658d0ee76a64480
|
Provenance
The following attestation bundles were made for similar_rs-0.1.1-cp39-abi3-macosx_11_0_arm64.whl:
Publisher:
wheels.yml on Maksim-Burtsev/similar-rs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
similar_rs-0.1.1-cp39-abi3-macosx_11_0_arm64.whl -
Subject digest:
6ac5f3845931550f426cad8e0eda776ebd637866a4799f4b6c2543757298a6dc - Sigstore transparency entry: 2627985676
- Sigstore integration time:
-
Permalink:
Maksim-Burtsev/similar-rs@61e7dea66fcba4140baf053a67cdacef9ec6474a -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Maksim-Burtsev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@61e7dea66fcba4140baf053a67cdacef9ec6474a -
Trigger Event:
push
-
Statement type:
File details
Details for the file similar_rs-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: similar_rs-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 674.3 kB
- Tags: CPython 3.9+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d40f118b65ce03d830c949f0879ff228447784a99d71b85613a3983277e96e4e
|
|
| MD5 |
31d5690392dc1c9489578b8675b7b47a
|
|
| BLAKE2b-256 |
b3e2ec3483ab58b88ed37a593248a3964d228406f3a6390152a4be243cf87ff0
|
Provenance
The following attestation bundles were made for similar_rs-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl:
Publisher:
wheels.yml on Maksim-Burtsev/similar-rs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
similar_rs-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl -
Subject digest:
d40f118b65ce03d830c949f0879ff228447784a99d71b85613a3983277e96e4e - Sigstore transparency entry: 2627985692
- Sigstore integration time:
-
Permalink:
Maksim-Burtsev/similar-rs@61e7dea66fcba4140baf053a67cdacef9ec6474a -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Maksim-Burtsev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@61e7dea66fcba4140baf053a67cdacef9ec6474a -
Trigger Event:
push
-
Statement type: