跳到正文
DEV Community· Anup Karanjkar·· 3 小時前AI 評分54

Google 以 Pyrefly 取代 pytype:2026 年 Python 類型檢查器比較與遷移指南

Google Replaces pytype With Pyrefly: Which Type Checker in 2026

AI 導讀

Google 已在全公司採用 Meta 以 Rust 編寫的 Pyrefly 作為 Python 類型檢查器,並棄用 pytype;Google 稱 Pyrefly 在內部基準測試中快一個數量級,並在 typing conformance suite 得分約 97%。

正文

Google has made Pyrefly, Meta's Rust-based Python type checker, its type checker across the company and is dropping pytype, and if your CI still runs pytype you are on a tool whose own README says Python 3.12 is the last supported version. Google's announcement dated 6 October 2026 reports Pyrefly as "an order of magnitude faster than Pytype" on its internal benchmarks and scoring roughly 97% on the official typing conformance suite[1]. The pytype repository was archived on 3 September 2026[2]. Below: what Google actually said, a four-way comparison of mypy, Pyright, Pyrefly and ty, a bug that a sound checker catches and a lenient one lets through, and a migration path you can run this week.

TL;DR

  • pytype is finished: its README names 3.12 as the last supported Python version and the repo is archived. Plan a move now, not when your next Python upgrade breaks it.

  • Pyrefly is the closest drop-in for pytype and mypy users who want speed: it ships pyrefly init to convert mypy or Pyright config, and runs next to your old checker while you review.

  • ty from Astral is fast too, but its own README calls it beta with no stable API yet, so treat it as something to trial rather than gate releases on.

  • Stay on mypy or Pyright if your team already has clean runs, plugins or editor setup you rely on. Speed alone is a weak reason to churn a green pipeline.

  • Migrate in this order: install, init, check locally, suppress the flood, add to CI beside the old checker, then remove the old one.

What Google announced, and what it did not

The post, "Adopting Pyrefly as the Python type checker at Google", was published on 6 October 2026 by the Google Python team[1]. It says Google used pytype internally for more than a decade, and gives its reasons for the switch. The reasons, summarised:

  • Speed. Pyrefly is written in Rust, and Google's internal benchmarks found it "an order of magnitude faster than Pytype". The post also reports incremental rebuilds up to 98% faster with a warm daemon, and a drop of more than 80% in daily peak compute used for Python type checking.

  • Spec conformance. Pyrefly tracks new Python versions and typing PEPs, which matters because pytype analysed compiled bytecode, and bytecode changes between Python releases. That design made new typing features hard to add.

  • Diagnostics. Pyrefly's errors point at the offending code with inline annotations and sometimes suggest a fix.

  • Soundness. Google's example is a function that wants an int being called with a value typed int | None. Pytype accepted it because one member of the union fit. Pyrefly rejects it and suggests narrowing with an is not None check.

The pytype side is stated just as plainly. The README says the team is making 3.12 the last supported Python version, attributes this to a bytecode-based design that has made new features hard, and encourages users to "investigate the mature and excellent alternative solutions for Python typing"[2]. It does not name a replacement. Google naming Pyrefly is a statement about Google's monorepo, not a recommendation for yours.

What the announcement does not give you is a deadline. There is no date after which pytype stops working on your code. The practical clock is your Python version: the day you move to 3.13 or later, pytype has nothing to say. If you are planning that upgrade, see our Python 3.15 migration checklist and put the type checker on the same list.

mypy, Pyright, Pyrefly and ty side by side

Every cell below comes from the project's own pages or its release metadata.

Checker Written in Maintainer Status Conformance Config file

| mypy | Python, compiled with mypyc[12] | The Python project (python/mypy on GitHub)[12] | stable; 2.4.0 on PyPI, 1 October 2026 | not published | mypy.ini, .mypy.ini, pyproject.toml ([tool.mypy]), setup.cfg, read in that order[6] |

| Pyright | TypeScript, runs on Node.js[13] | Microsoft[7] | stable; 1.1.414, 9 September 2026 | not published | pyrightconfig.json, or [tool.pyright] in pyproject.toml; the JSON file wins if both exist[13] |

| Pyrefly | Rust[1] | Meta (default checker for Instagram's codebase, now also Google's)[1][8] | README: "current development status is stable"; latest release v1.4.0, 15 October 2026[8][9] | roughly 97% on the typing conformance suite, per Google[1] | pyrefly.toml or [tool.pyrefly] in pyproject.toml[4] |

| ty | Rust[10] | Astral[11] | README: "currently in beta", 0.0.x versions, no stable API yet[11] | not published | ty.toml, or [tool.ty] in pyproject.toml[14] |

Editor support: Pyrefly lists extensions for VS Code, Neovim and Zed[8]. ty ships a language server with completions, code actions and inlay hints, with integrations for VS Code, PyCharm and Neovim[10]. Pyright's README describes a command-line tool plus a Visual Studio Code extension[7].

Two readings of this table. First, only one tool in it has a published conformance number and it comes from Google, a user with an obvious interest in the result. Run the conformance suite yourself if the number decides your pick. Second, "stable" and "beta" are the projects' own labels; they say nothing about how many errors each will raise on your code.

The class of bug a sound checker catches

The example below is ours, not Google's, but it has the shape their post describes: a value that might be None flows into a function that needs a real number.

def discount_for(age: int) -> float:
    return 0.2 if age >= 65 else 0.0

def checkout_total(ages: dict[str, int], name: str, price: float) -> float:
    age = ages.get(name)          # int | None
    return price * (1 - discount_for(age))   # flagged: None is not an int

If name is missing from the dict, ages.get returns None, and age >= 65 raises a TypeError at runtime. It only fires for unknown customers, so tests with seeded data never hit it. A checker that treats int | None as acceptable because one half of the union fits will pass this file. A sound union check will not. The fix is to narrow before the call:

def checkout_total(ages: dict[str, int], name: str, price: float) -> float:
    age = ages.get(name)
    if age is None:
        return price
    return price * (1 - discount_for(age))

Expect the first run on a mature codebase to turn up dozens of these. Most are real latent bugs; some are places where an invariant you know about is invisible to the checker. That split is the whole migration problem, and the next section is about handling it without freezing the team.

Migrating from pytype or mypy to Pyrefly

The steps below follow Pyrefly's migration page[3]. Pyrefly documents conversion from mypy and Pyright configs; it does not document a pytype importer, so a pytype project starts from a fresh config.

1. Install beside your current checker

uv add --dev pyrefly
# or
python -m pip install pyrefly

2. Generate a config

If you have a mypy or Pyright config, run pyrefly init to convert it. The migration page warns that unrecognised settings are skipped without a warning, so diff the generated file against your old one before committing[3]. Pyrefly reads pyrefly.toml at the project root, or a [tool.pyrefly] section in pyproject.toml. Without an explicit -c flag it searches upward for pyrefly.toml, pyproject.toml, setup.py, mypy.ini and pyrightconfig.json, and if it finds no Pyrefly config it may migrate a nearby mypy or Pyright config in memory[4]. A minimal pytype-era start looks like this:

# pyrefly.toml
project-includes = ["src"]
python-version = "3.12"

Those two keys are the ones the configuration docs use in their own example. If you do not set python-version, Pyrefly queries your interpreter and falls back to 3.13.0 when that fails[4], which is worth pinning explicitly in CI.

Create the config before your first check. With no pyrefly.toml or [tool.pyrefly] section and no mypy or Pyright config nearby, Pyrefly falls back to its basic preset, which only reports high-confidence error kinds and stays silent on the None-to-int mismatch above. A pytype project has nothing to migrate, so run pyrefly init (it writes a pyrefly.toml, or a [tool.pyrefly] entry if you point it at pyproject.toml) or write the file by hand[4]. We ran Pyrefly 1.4.0 on the example from this post: 0 errors under the basic preset, then one bad-argument-type error once a pyrefly.toml with project-includes existed.

3. Run it

pyrefly check

Your old config stays in place, so both checkers can run while you review[3].

4. Handle the error flood

Pyrefly documents two routes[5]:

  • Suppression comments. Add # pyrefly: ignore on a line, or target one error kind with # pyrefly: ignore[bad-return]. For a whole file, # pyrefly: ignore-errors at the top. To add them in bulk, run pyrefly suppress (equivalent to pyrefly check --suppress-errors), and add --comment-location=same-line if you want comments on the error line.

  • A baseline file. This records current errors so CI reports only new ones, with no edits to source. Generate it with pyrefly check --baseline="baseline.json" --update-baseline and check against it with pyrefly check --baseline="baseline.json". The docs label this feature experimental, so read the current page before you depend on it.

Bulk suppression is the fast route and it leaves a visible to-do list in the diff. The baseline keeps the diff clean but hides the debt. Pick one per repo; mixing them makes it hard to say what is left. Later, pyrefly suppress --remove-unused clears suppressions that no longer match an error[5].

5. Put it in CI, then retire the old checker

Run pyrefly check as a second job beside pytype or mypy for a sprint. The migration page says you can keep both in CI, and its last step is removing the old checker and any ignore comments it left behind once you are ready[3]. It gives no CI snippets, so wire it into whatever job runner you already use. If you also manage AI-assisted Python work, a pinned checker command in your agent instructions stops an assistant from "fixing" errors by adding ignores; our Claude Code configuration pack for Python backends is one place to put that rule.

When to stay on mypy or Pyright

Google's move solves Google's problem: a monorepo, a bytecode-based tool that could not keep up, and a compute bill measured in thousands of cores. Few teams have that problem. Stay put when:

  • Your mypy or Pyright run is green, fast enough, and trusted. A migration that produces 400 suppressions and no new bugs found is a cost with no return.

  • You depend on a mypy plugin for a framework or library. Whether a plugin has a Pyrefly equivalent is something to check against your own dependency list before you start; this post does not claim parity for any specific plugin.

  • Your editor experience is built on Pylance or Pyright and the team likes it.

  • You need a stable-labelled tool today and ty's beta status rules it out, while your goal is just speed. Pyrefly's README calls it stable; ty's calls itself beta.

The reverse case is real too. If your type-check step is the slowest thing in the pre-commit loop, or you are still on pytype, trialling Pyrefly costs an afternoon: install it, run pyrefly check, and count the errors. That number tells you more than any benchmark. If it is a handful, switch. If it is thousands, suppress, baseline, and schedule the fix-up work. Related reading for a typed Python service: FastAPI production API best practices. For quick diffs of config files while you migrate, the diff checker and JSON formatter run in the browser.

Frequently asked questions

Is pytype still usable?

Yes, on Python 3.12 and earlier. Its README says 3.12 is the last supported version, and the repository is archived and read-only[2]. It will not gain support for newer typing features.

Does Pyrefly import my mypy config?

It converts mypy and Pyright configs with pyrefly init, but unrecognised settings are skipped without a warning, so review the output[3]. It does not document a pytype config importer.

What version is Pyrefly at, and is it stable?

The newest release is v1.4.0, published 15 October 2026. Pyrefly 1.0.0 was tagged on 12 May 2026[9]. The README says its development status is stable[8].

Should I use ty instead?

ty is a Rust checker and language server from Astral and is worth trialling, but its README says it is in beta and does not yet have a stable API[11]. Try it locally; do not make it a release gate yet.

How do I stop CI from failing on hundreds of old errors?

Use pyrefly suppress for one-time bulk comments, or the experimental baseline file so CI reports only new errors[5].

Is the 97% conformance figure independent?

No. It is the figure Google reports in its own announcement[1]. Run the typing conformance suite on the versions you plan to use.

Sources

  1. Google Open Source Blog: Adopting Pyrefly as the Python type checker at Google (6 October 2026)

  2. google/pytype README (archived 3 September 2026)

  3. Pyrefly docs: migrating to Pyrefly

  4. Pyrefly docs: configuration

  5. Pyrefly docs: error suppressions and baseline files

  6. mypy docs: the mypy configuration file

  7. microsoft/pyright README

  8. facebook/pyrefly README

  9. facebook/pyrefly releases (v1.4.0)

  10. Astral ty documentation

  11. astral-sh/ty README

  12. python/mypy on GitHub (README: mypyc-compiled mypy)

  13. Pyright configuration docs (and packages/pyright-internal, a TypeScript package)

14. ty configuration docs

Originally published at wowhow.cloud

來源:DEV Community · dev.to