Emacs 26, Mojave, elpy, readline
I first started having problems with macOS readline and macports Python a year or two
ago. Initially, it was bugs in resetting the tty to a sane configuration when a Python
REPL exited. That seems to have been solved, but I'm now encountering readline
problems with Python 3.7, GNU Emacs 26.1, and elpy. These notes describe what seems
to be a solution, at least for the time being.
I typically install Python versions like this via macports:
sudo port install python37 sudo port install py37-pip sudo port install py37-virtualenv sudo port install py37-virtualenvwrapper
Subsequently, I'll use the Python through virtual environments, such as:
mkvirtualenv -p python3.7 py37
With Python versions 3.5 or earlier, it is necessary to use gnureadline to work around
problems in the macports readline which uses libedit. This can be done by
installing py-gnureadline with macports and configuring it as the readline via
$PYTHONSTARTUP. Both the REPL and elpy work fine with this configuration.
With Python 3.6+, gnureadline works properly with the REPL, but elpy has problems
with it, preventing inferior Python processes from working properly with Emacs.
Workaround
This is how I resolved the elpy problem.
At this point in the process, there is a ~/.virtualenvs/py37/lib/python3.7/readline.so,
which is a symbolic link to
/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload/readline.cpython-37m-darwin.so.
This is the libedit readline.
Use easy_install to (not pip)
install gnureadline.
sudo easy_install gnureadline
This installs gnureadline in
~/.virtualenvs/py37/lib/python3.7/gnureadline-6.3.8-py3.7-macosx-10.12-x86_64.egg.
Once installed, gnureadline is functional, at least in $PYTHONSTARTUP and in ordinary
python code. elpy also works when editing python code. However, elpy fails when
sending code to a python process. One can test this by first starting an Emacs via
Emacs -Q and then running the command M-x run-python. When I did this, I received
warnings like the following:
Warning (python): Your ‘python-shell-interpreter’ doesn’t seem to support readline, yet ‘python-shell-completion-native-enable’ was t and "python" is not part of the ‘python-shell-completion-native-disabled-interpreters’ list. Native completions have been disabled locally.
The failure, I think, is due to path precedence problems in sys.path which cause the
libedit readline to be used instead of gnureadline. In any event, I found a
workaround.
The final setp in the workaround is taken from
here,
which renames the libedit readline so that it can't be found.
cd /opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload
sudo mv readline.cpython-37m-darwin.so mv readline.cpython-37m-darwin.so.bak
The solution leads me to believe that, somewhere in elpy, is code that loads
gnureadline if it cant find readline.
Regardless, with the rename, python inferior processes work correctly. And, fortunately, my
$PYTHONSTARTUP
continues to work properly as well.