How I work on Python 2 and Python 3 with the Python Language Server (in GNU Emacs)

Python is one of the programming languages that I usually edit in GNU Emacs. These days, that means using the Language Server protocol through lsp-mode and the pyls Python language server . Back when I first set this up and wrote early notes on using LSP-based editing of Python , I had not solved the problem of wanting to edit both Python 3 and Python 2 based code in my GNU Emacs sessions.

If you want to do this, it turns out to be important to run either the Python 2 pyls or the Python 3 pyls , depending on whether the file you're editing is written in Python 2 or Python 3. This creates several problems that I had to solve, and eventually did with brute force (if I used Python virtual environments, it probably would be easier).

First, it's obviously necessary to install both versions at once. I install pyls into $HOME/.local/ by using pip's '--user' switch, so I created a .local/bin/py2-pyls subdirectory and manually moved the Python 2 version of pyls from .local/bin into it. This requires me to always update the Python 2 version of pyls before the Python 3 version, which is a bit annoying, but that's life in a world of both versions.

To pick the right version of pyls to run, I use a cover script; the cover script uses various heuristic checks to try to figure out if it's being run in a directory with Python 2 or Python 3 code (it doesn't work for the case of mixed code and I'm not sure that would work in general anyway). I don't have $HOME/.local/bin on my $PATH and GNU Emacs will conveniently just try to run ' pyls ' to start the Python LSP server, so I put the cover script in my $HOME/bin.

The most important checks the cover script uses are to look for which version of Python seems to be being run by '#!' lines in any *.py files in the current directory, and whether there are any obvious ' print ' statements (which indicate Python 2). If you're going to do this, note that some Python programs are installed with their '#!' line being '#!/usr/bin/env python3' or the like, instead of directly running the Python interpreter. I missed this in the first version of the cover script because all of our Python scripts directly use '#!/usr/bin/python3'.

(Also, the default Python version for my cover script is Python 3, because Python 3 is what I'm writing all my new Python code in.)

All of this is basically a hack but it works pretty well for me, especially in combination with how I'm dealing with my Python indentation problem . The result is a pretty seamless LSP-based Python editing experience in GNU Emacs where everything basically works. I'm not sure I'm sold on the whole LSP-based experience for editing Python, but that's not the fault of my hacks.