A new to me LSP server for Python has appeared: basedpyright. This is a fork of the fast pyright langserver which Microsoft develops, with a more OSS philosophy. It has lots of improvements bringing it close to (and in some cases surpassing) the proprietary, MS VSCode-only LSP server pylance which wraps pyright:
Basedpyright is a fork of pyright with various type checking improvements, improved vscode support and pylance features built into the language server.
You can read about all the improvements over pyright. The one most meaningful to me is "docstrings for compiled builtin modules". E.g. docs with eglot go from:
pyright:
class range(
stop: SupportsIndex,
/
)to
basedpyright:
class range(
stop: SupportsIndex,
/
)
range(stop) -> range object
range(start, stop[, step]) -> range object
Return an object that produces a sequence of integers from start (inclusive)
to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.
start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.
These are exactly the valid indices for a list of 4 elements.
When step is given, it specifies the increment (or decrement).
Recent eglot versions already support it: just pip install basedpyright. Works fine with lsp-booster and all the normal settings.
Python. So many lsp-server options. Which one is "the right one"
Frustrating python lsp experience
Videos
After years of enjoying freedom from writing Python code, I now find myself reluctantly returning to this once familiar territory, and almost instantly got overwhelmed with decision fatigue.
At the moment, I can't figure out which lsp-server to use. There's:
-
pylsp,
-
jedi,
-
palantir-made (deprecated),
-
microsoft made (deprecated),
-
microsoft made pyright,
-
stripped down version of it - pyright-based,
-
rust made ruff,
-
PyDev (does it even work with Emacs?),
-
C#-made, archived and unmaintained python-language-server
It'd be fine if there was just some overlapping functionality, but it seems they all have some features that just don't work. Like for example python-lsp-server can't let you browse workspace symbols. Which for me, honestly, really is a deal breaker. I use consult-lsp-symbols command all the time.
And then after choosing an lsp-server, I have to tune up some checking, linting features, and I'm not sure which one of these are "relevant": black or yapf or ruff, flake8, rope, mypy, pydocstyle, pylint, jedi; OMG, why are there so many linters?
What do you folks use? I thought configuring Emacs for web dev these days was a hassle - I had no idea how messy the Python world has become.
I'm losing my mind over emacs as a python IDE. It seems that no matter which LSP concept I attempt, the experience is suboptimal. At best it is riddled with odd issues, and at worst almost bordering unusable.
I work as a python developer, and I work on quite large code bases. The LSP experience is essential for me given the complexity, but I'm at the point of giving up, even though I've been an emacs user for the better part of a decade.
I use doom emacs, by the way, but I'm quite happy to try anything to solve this. I have considered to build an emacs config from scratch again to see if I can narrow down the experience, but right now I have not invested the time. But again, considering how frustrated and desparate I am, everything is on the table.
Let me describe what I need and what I've tried.
My requirements
I need my lsp to understand my environment in order to load in a custom PYTHONPATH variable. This I handle with a .envrc file and the emacs module envrc. This has worked without any problems so far.
For the actual LSP, I use python-lsp-server but I am not at all religious about it.
I run mypy on my codebase, and I'd like to use ruff for checking/formating, but I've used the other tools (pycodestyle/black) for now.
lsp-mode
The lsp-mode is the one that is closest to being good, had it not been for the abysmal behavior over time. It seems that some memory leaking happens, and over time it becomes sluggish, sometimes blocking emacs for multiple seconds.
eglot
Eglot seems a lot faster, but has functional problems. I've often had to restart eglot when opening new python modules. I've tried to use eglot for months now, accepting the quirks to gain the speed, but the restart behavior is annoying, and I often get weird errors such as error in process filter: Wrong type argument: plistp, [] repeatedly until I restart eglot again. No luck debugging that error so far either.
I'm also not super excited about the .dir-locals.el approach to customization, but should the other issues resolve, I'm willing to figure that one out.
lsp-bridge
I was quite excited to hear about a third option that was super fast. However, I've not manage to get it to work with the envrc package, so I've parked that one.
So, I turn to you, kind strangers on the internet. Do you have a well-functioning python LSP setup in emacs? Have you experienced some of the issues that I have described and did you manage to solve it?
Do you perhaps have a described approach to building a great python setup with emacs? Please help me!