Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Pyright: Static Type Checker for Python (github.com/microsoft)
152 points by pen2l on Jan 2, 2023 | hide | past | favorite | 57 comments


To the obvious question: how does this differ from mypy?

tldr; mostly about performance improvements but there's also semantic differences. The latter sounds like it means a split between the community who decides to do mypy vs pyright. But maybe pyright only differs with mypy in terms of things that are considered bugs in mypy, and things that are optional in mypy (via flags).

https://github.com/microsoft/pyright/blob/main/docs/mypy-com....


I’ve heavily used both mypy/pyright.

The semantic differences are mainly in areas where type system is not specific enough on exact behavior expected. As an example if you have a function that has overloads how do you decide which overload to pick? Sometimes that can become ambiguous especially when type variables are involved or multiple overloads match. Cases like that are where you see most intentional differences and as a user of both type checkers I consider depending on specific behavior there to be like using c++ compiler’s undefined behavior.

The bigger area I see differences is feature development/bug fix velocity. Mypy is maintained well. Pyright is maintained magically and I’ve reported bugs that maintainer fixes the same day. Most bug reports to pyright get fixed in a week. Only a couple tend to stay open for a while. New type system features (peps) get implemented really fast in pyright and usually if you try to use very recent features you will need to wait a while for mypy to catch up. A good example is release time for paramspecs or typevartuple. Most of the time new type system peps are added in pyright while still in draft stage.


An important difference is that pyright doesn't support plug-ins.

https://github.com/microsoft/pyright/issues/607

E.g. https://github.com/Shoobx/mypy-zope can't work with pyright


After quickly skimming that issue thread I think the Pyright devs have a very compelling argument not to add a plug-in system. It would encourage none standard behaviour, when really the type system should be capable of describing all behaviour. I think it may be another plus for it.


I appreciate that argument but some codebases are heavily reliant on “magic” libraries like SQLAlchemy. The SQLAlchemy mypy plugin helps a lot. Well, at least with SQLAlchemy 1.4; dunno if 2.0 needs the plugin


we've worked very heavily with the pyright developers directly on some aspects of SQLAlchemy 2.0, namely the new dataclasses feature : https://docs.sqlalchemy.org/en/20/orm/dataclasses.html#decla...

that said, the codebase primarily targets mypy for internal type checking; we tried targeting both tools simultaneously but there were great differences between both tools, which tended towards doubling our workload in getting everything to pass typing fully. In more than one case there were areas where the two tools would mutually disagree with each other, making "correct" typing impossible. This was some iterations back and mypy has had a lot of good releases since then (pyright has had many more, obviously).

when typing a large codebase, there are invariably lots of areas where you just need to "type: ignore" or otherwise do some non-ideal workarounds. it's in that area that trying to target more than one type checker at once gets to be really difficult.


Sweet! I might have to work on upgrading us from 1.4 to 2.0


I ran into this issue recently. 2.0 will not need the plugin and work with any Python type checker! So much so that the plugin is already somewhat deprecated.


That is most welcome news. I use VSCode, and the amount of unparseable magic makes working with the library more annoying than I would like.


Yup. Lots of casting or # type: ignore for now.

Here's an official bit about the new types: https://docs.sqlalchemy.org/en/20/changelog/whatsnew_20.html...


Seems like dubious logic to me. For example the Django ORM is quite big. Just saying that the type system should handle it and giving up on Django is not a pragmatic choice.


The most important difference in my experience has been that pyright is a lot more rigorous and correct than mypy. I found that it was easy to confuse mypy, leaving large amounts of code unexpectedly not type checked. Put simply, I trust pyright and I do not trust mypy.

You also have a lot more control with pyright over where unknown types are permitted or what other checks should be performed. Also, it can scan library source code to infer types which I don't think mypy supports.


My experience is much the same: pyright is fast, reliable, and (when it complains) correct. MyPy is… not always those things. The teams I know that use Python generally have all moved to pyright if they started with MyPy.

The lack of plug-in support might feel like a hang-up, for instance if you’re using Django. FWIW, I like the “no plug-in” philosophy. I’ve discovered that explicitly adding annotations that a MyPy plug-in would have surmised feels cleaner. (Example: an annotation for a reverse collection on a Model referenced by a foreign key.) Even better: I don’t need to suffer the (in my experience) frequent bugs of the plugins themselves.


An example of where mypy chokes:

  def foo(data: list[str]):
    r = []                        # error: Need type annotation
    for key in data:
      r.append(key if len(r) > 0 else '')
    return r


A bit more specifically, looks like pyright was designed to serve as a language server for VS Code.

This means being able to incrementally type check incomplete code blocks and to also infer & suggest types, where mypy is too slow and/or just doesn’t support those features.


Pyright was designed by Microsoft to serve as the core of a proprietary[1], DRM-locked[2,3] Python language server, yes.

[1] https://github.com/microsoft/pylance-release/issues/4

[2] https://github.com/microsoft/pylance-release/issues/746

[3] https://parsiya.net/blog/2021-12-20-rce-in-visual-studio-cod...


You don't have to use Pylance though, just use Pyright itself. While it's a shame that Pylance isn't open source, I won't fault anyone for not doing so, that's their choice, just as I don't open source all of my code either.


I do fault them, a bit, philosophically, but that’s not even the core of my complaint here. I may not like Microsoft releasing proprietary software, but I hardly feel surprised or cheated when they do.

On the other hand, when Microsoft creates an interoperability standard to solve the proliferation of wheel-inventing in IDEs, actively promotes it as such, creates and supports an open-source implementation of it for Python as part of said promotion, then abandons[1] said implementation in favour of a proprietary one that deliberately speaks the interoperability protocol in a slightly non-interoperable way, then yes, I do feel like I’ve been conned, and maybe I should stop treating Microsoft’s open-source efforts seriously even if they’re good software at the present moment. (Whether my level of cynicism regarding Microsoft should have been high enough that I wouldn’t have been surprised, I’m not sure.)

[1] https://github.com/microsoft/python-language-server/issues/2...


Pylance is used in a number of Microsoft products, quite a few of which are not open source, whereas the previous language server was only used in the VS Code and VS Python extensions, which are open source. There's your license difference explanation. As to why the old language server was retired, it had a different architecture which involved reindexing all the code all the time, and the team couldn't make it performant enough; pyright lazily evaluates just what is needed at the point it is needed.


Well, others are free to make their own language servers if they don't like the current implementations, just as we do with other proprietary software, ie GIMP vs Photoshop.


Again, “Microsoft creates proprietary software” (which is what your comment is responding to) is no news; “Microsoft starts interoperable ecosystem, gets everyone on board, then deliberately goes against the ecosystem’s interests” (which is incidentally accomplished by creating proprietary software) is my problem.

Authors of other language servers deliberately chose to put up with Microsoft’s legacy-induced craziness in the protocol (positions in UTF-8-encoded strings specified as UTF-16 code unit counts, etc.) due to Microsoft’s promise of an interoperable ecosystem; then Microsoft reneged on that.

I’d have much less of a problem, for example, if I could use a proprietary Pylance with VS Codium or Neovim or whatever else I want; I’d have almost no problem if Microsoft also hadn’t published then abandoned an open-source Python language server first. But I can’t, and they did.


I don't see a problem where you do, it seems. Anyone is free to make or not make whatever they want, that they made the ecosystem is enough for me, I've already derived enough benefit from it through interoperability with Neovim as well as VSCode, they simply don't have to make anything else beyond that; even if they initially started and stopped working on a Python language server, that is their prerogative. The ecosystem is no less interoperable just because they made a proprietary language server instead.


Microsoft's motto: embrace, extend, extinguish.


The situation gives me a weird déjà vu.


Mypy has mypyd [1] to run fast live type checking. Things like pylsp-mypy [2] use it automatically by default.

[1]: https://mypy.readthedocs.io/en/stable/mypy_daemon.html

[2]: https://github.com/python-lsp/pylsp-mypy


The last time I actively looked into it (granted, some months ago), it was somewhat hindered by https://github.com/python/mypy/issues/9309 causing it to re-evaluate sources quite a lot during editing even with mypyd.

I just had a quick check and can't obviously see if that has been fixed/worked around in pylsp-mypy, on the off-chance that you might know :)


Cool, didn’t know that!


From this comparison (https://github.com/microsoft/pyright/blob/main/docs/mypy-com...) it looks like Pyright fixes a load of issues that MyPy has. It also seems much closer to how TypeScript works (I have worked significantly more with TypeScript than typed Python and really like it)

Is there a reason not to go with Pyright and stick with MyPy?


Typescript similarity is expected as maintainer of pyright does talk with typescript maintainers and sometimes pyright adds features inspired by typescript's inference.

I think the major reasons for mypy is if you are working on a library to be shared with many others (especially open source one) you'd like library to be compatible with mypy as your users are likely to use mypy as it's still most popular type checker. So for open source libraries it makes sense to use both mypy/pyright. For projects that you do not expect main users (company internal one you define standards) it's more fine to pick type checker you prefer. The other main place mypy can be helpful is plugins if you need some behavior outside of type system for a library you work with a lot.

Also pyright is implemented in typescript which does mean you'll need to have a CI dependency on javascript environment that python project's often don't need. Lastly for typical python developer it's a bit easier to make pull request to mypy vs pyright just as they normally have more python knowledge then javascript knowledge. This is pretty minor given most people don't debug there own type checker and pyright's bug list is very short.


Mypy supports plugins. That's the only advantage I'm aware of. I like Pyright because it has a track record of adding new type features months ahead of Mypy (e.g. recursive types, ParamSpec).


Pyright doesn't support narrowing based on object truthiness and some other python isms.

In my experience, mypy tends to be more correct and correctly understands more python code.

For example, the following won't type check in pyright (it doesn't infer the type of out):

    out = []
    for x in bar:
      out.append(x \* 2)
    return out
Edit: also pyright's vendoring of type stubs is annoying as they take precedence over downloaded type stubs.

Edit2: also lack of plugins, makes using things like Pydantic less type safe compared to mypy


Pyright's vendoring of stubs or pylance's? Pylance vendors extra stubs (microsoft type stubs), but pyright itself does not. Pyright does vendor typeshed, but all type checkers including mypy vendor typeshed.

Narrowing on object truthiness unsure what you mean. That's intended to be supported. The out example is real difference where mypy does do better. It should at least type check on basic pyright but won't type check on strict without doing out: list[int]. That one comes from mypy has special handling for lists to allow inferring type of elements later, while pyright always infers type of a variable only based on it's declarations and never it's method calls like append.


If you have a tagged union type with Boolean literals as the tags, like in the slack api, then you can’t say ‘if not res.ok’ to narrow the type, you have to say ‘if res.ok == True’

Which isn’t very pythonic imho

Also I’m pretty sure ‘if res.ok is True’ doesn’t work


The precedence should be: "typing" folder in workspace root -> project "extra paths" -> python search paths -> pylance bundled.

If that's not working for you you should open an issue at https://github.com/microsoft/pylance-release.


I've been using pyright more than mypy these days; playing with higher order functions I have pulled about half of my hair out because of things that more often than not turn out to be mypy bugs. I've tried pyre, and that's better too, in my experience. The codebases of mypy and pyre are starkly different in terms of organization (though pyre does the heavy lifting in OCaml). Haven't looked at pyright's yet.

Besides the bug count, it's kind of weird to see the "reference" type checker for Python constantly lagging behind in terms of features, experimental ones but also ones that have already been accepted PEPs for a while. Meanwhile pyre and pyright both have usually had features for _months_ before mypy has even started implementing them.

As a side question, does anyone know how I can easily interface with an LSP client from Python? I'm itching to build something that gives me some custom typing insight as I write code, and it's probably more robust to consult LSP than to parse CLI output.


I don’t know if this helps with your actual problem but if you use vscode you can enable inline typehints and all variables will show their inferred types right in the editor. I personally find it too noisy but it sounds almost like what you want to build so thought I’d mention it.


Has anyone migrated a large code base between MyPy and Pyright? In particular would love to hear about experiences with Django. Mypy’s performance and the join based type merging are quite limiting. At the same time, the ecosystem support around MyPy seems strong.


Django is one library that has some apis that are beyond type system and likely difficult to ever fully describe in type system. Some of this it handles with a custom mypy plugin to overrule/extend some type rules. No other python type checker I'm aware of supports plugins so this is one place mypy will have an advantage. Usually when behavior is too dynamic to be described well the stubs will fallback to Any leaving some typing holes for other type checkers.

At same time this only affects a subset of Django behavior and I have used pyright with a Django codebase and it mostly worked well. The more you use very dynamic features of Django the more this matters.

One note for both is you do want to tune configuration settings. Pyright basic is fairly easy to satisfy, pyright strict is too hard for most codebases. Similarly mypy defaults are too lenient, but mypy strict is pretty hard (even mypy doesn't use strict to check itself). I roughly go for strict for both and then remove ~5 hardest rules and call that good enough. Strictest rules pretty much require all of your dependencies to be well typed/stubbed.


Yes. I moved a very large/mature Django project from use of MyPy to use of Pyright. My experience was that pyright flagged a bunch of new conditions that MyPy seemed to have missed. The cost was that I needed to add (many!) explicit annotations or casts in places the Django MyPy plug-in would have just “known” about the types, for instance in foreign key relations in Models.

In general, we were very happy with the result and never looked back. Correctness and perf were both notably improved. (That pyright is also part of pylance, Microsoft’s proprietary LSP implementation for Python that plays well with VSCode, was an advantage for this particular team.)

This was about a year and a half ago so the experience may differ; both pyright and mypy + its plugins have gotten more capable and mature over time.


I can't decide if it's a feature or a bug that there are at least 3 major type checkers for Python.


It's a consequence of Python never having been designed as a language with a static type system. In fact, Python is utterly dynamic and has a number of mechanisms that allow to write code which defies and mocks any attempts at static typing.

When the pain of maintaining larger codebases resulted in attempts to add static type checking (ultimately successful), it was, and still is, impossible to produce a solution that would work equally well for all kinds of codebases. Stricter tools show too many "false positives", laxer tools miss too many cases that a real static type checker would flag. Say, things that Django does (not to mention Zope) can only be described well by special-casing them. Hence different tools which strike different kinds of compromises.


> It's a consequence of Python never having been designed as a language with a static type system

Is it? Mypy is semi-official and has Guido as a contributor. It also predates both pyright and pyre by many years.

Honestly I find it somewhat sad that huge tech companies create their own instead of contributing to an existing and popular implementation. But perhaps the internal versions predated Mypy by a lot.


Pyright is pretty recent and started development years after mypy. But some of pyright's design goals (laziness for LSP) would have made it very difficult to do in mypy without a very large refactor/rewrite. Pyright is implemented in typescript for better LSP/vscode integration and performance. pytype (google's type checker) is only one I know that predates mypy for when it started development.

Pyre's reason is interesting, https://github.com/facebook/pyre-check/issues/38. Pyre is based off of Hack, facebook's php compiler. Facebook made pyre to re-use tooling/techniques from Hack on python. Secondary reason is performance. Pyre is done in OCaml and having same performance in type checker implemented within python is hard.


I can vouch for use of Pyright as LSP for neovim and helix. Very useful, especially the strict mode.

I usually pair it with pyre, another great tool

https://github.com/facebook/pyre-check


Could you comment on why you use both pyright and pure?


Better late than never :)

FB people have great experience with introducing typing into weakly typed languages (e.g. PHP vs Hack). So I actually started using pyre-check in place of mypy. The tool is really great and fast. I also like pysa quite a lot.

Pyright only came into focus because it was best Python LSP implementation for NeoVim, and it is also the default for helix-editor which I play with. It's also nice that I could suggest pyright for some younger colleagues using VisualStudio Code (with strict mode enabled of course).

P.S. I'm also using other interesting tools and libraries from FB (Instagram) like libcst [1] or fixit [2]

[1] https://github.com/Instagram/LibCST/ [2] https://github.com/Instagram/Fixit


I use both mypy and pyright. Pre-commit hook/vscode runs checks for mypy, pyright, as well as pylint, flake8, black, bandit.

Why both? I just have more confidence in getting feedback from both of the tools.


For Neovim users that use LSP + completion + snippets, it is slightly unfortunate that the Pyright team does not plan to support snippets on Pyright (but open to supporting it on Pylance, which is not OSS).

https://github.com/microsoft/pyright/issues/924


Related:

Pyright: Static type checker for Python - https://news.ycombinator.com/item?id=19473631 - March 2019 (87 comments)

Also:

Using Mypy in Production - https://news.ycombinator.com/item?id=32556816 - Aug 2022 (129 comments)

Exhaustiveness Checking with Mypy - https://news.ycombinator.com/item?id=25428583 - Dec 2020 (19 comments)

Applying Mypy to real-world projects - https://news.ycombinator.com/item?id=22302789 - Feb 2020 (23 comments)

Statically-typed error handling in Python using Mypy - https://news.ycombinator.com/item?id=21736620 - Dec 2019 (126 comments)

Pytype – A static type analyzer for Python code - https://news.ycombinator.com/item?id=19476605 - March 2019 (29 comments)

Pyre: Facebook's static type checker for Python - https://news.ycombinator.com/item?id=19476286 - March 2019 (2 comments)

Type hints cheat sheet (Python 3) - https://news.ycombinator.com/item?id=18660309 - Dec 2018 (18 comments)

PyAnnotate – Auto-generate type annotations for mypy - https://news.ycombinator.com/item?id=15707877 - Nov 2017 (33 comments)

Static types in Python - https://news.ycombinator.com/item?id=12703008 - Oct 2016 (221 comments)

Typed Python: new Mypy release - https://news.ycombinator.com/item?id=11641245 - May 2016 (46 comments)

Mypy 0.3 Released – optional static type checker for Python - https://news.ycombinator.com/item?id=11134647 - Feb 2016 (19 comments)

Mypy – static type checking for Python 3 - https://news.ycombinator.com/item?id=8191916 - Aug 2014 (29 comments)

Mypy - An experimental Python variant with dynamic and static typing - https://news.ycombinator.com/item?id=4561973 - Sept 2012 (39 comments)


Moved Colour to Pyright a few weeks ago, our Mypy checks on Github Actions were taking 1h30. Those speed regressions were fixed recently though but Pyright is still much faster and seems stricter, finding more legit issues than Mypy.


Microsoft: "Where do you want to go today?"

https://youtu.be/T4oNA8ViuwI?t=63


It's written in Typescript I would love to type check python in the browser without running pyodine, does anyone know how?


The Micro:bit Educational Foundation do it for https://python.microbit.org/ where the scope is conveniently limited (to MicroPython running on a device with finite flash/RAM)

https://github.com/microbit-foundation/pyright (and more specifically https://github.com/microbit-foundation/pyright/blob/microbit... )


Oh wow, their pyright-browswr package is very nice, the writeup works well!



Wow that's pure gold


better (more suggestive) name than "mypy"




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: