2020-02-18
I have an old post describing how
to spin up an IDE-like Python development environment in Emacs with
Eglot and some .dir-locals.el
help. Now a year later, I've converged on what I think is a better
setup.
My main driver for installing different versions of Python and
spinning up virtual environments is pyenv. I use the automatic
installer on all machines where I install pyenv, and I manually
modify my shell's initialization such that I have to execute a
setupPyenv
function to enable its usage (I also give myself the
ability to activate an environment via a single argument):
To activate various Python environments in Emacs I turn to
pyvenv. Since the pyenv
installer puts itself in the user's home
directory, we can configure pyvenv
to find virtual environments
in ~/.pyenv/versions
via the WORKON_ON
environment variable.
I lean on use-package
to initialize pyvenv
and set the
environment variable:
By setting the WORKON_HOME
environment variable we can select
which pyenv
virtual environment we want to use by calling M-x pyvenv-workon
. One can also call M-x pyvenv-activate
to choose
an environment via manual filesystem navigation.
With a pyvenv
environment activated in Emacs, all we have to do
is call M-x lsp
(after setting it up of course); lsp-mode can be
configured in an init.el
file with something as simple as:
See the GitHub project for more details. Completion (with
company-mode) and static checks (with Flymake, an Emacs builtin,
or Flycheck) are easy to setup with lsp-mode
.
The working virtual environment will have to have a language
server installed. The easiest and fastest way to get started (a
simple pip install
) is to use pyls. Alternatively, one can use
Microsoft's python-language-server with lsp-mode via
lsp-python-ms; upon first use a prompt will ask if the user would
like to download mspyls
. I've used both; while mspyls
has
better performance, pyls
support is built into lsp-mode
and
the server can be installed like any other Python package (the
Microsoft implementation is a C# program). In my opinion those
pros neutralize the performance con (which is not too bad).
Just about all of my Python development happens inside of a
projectile project. I have a simple interactive function that will
automatically activate the environment associated with a project
and spin up lsp-mode. I bind this helper function to C-c C-a
in
the python-mode-map
.