Python and Emacs Pt. 1
Python
Python is my programming language of choice. I first started learning Python in the early 2000's and it was the first programming language which just "clicked" for me.
I have never worked on large projects before, though some of my person projects have grown fairly large. So I cannot speak to the effectiveness of Emacs as an IDE for large projects, I can tell you that I use it for Python all the time.
Today, we will focus on getting the code linting, auto-completion, and other sorts of features you find in a traditional IDE into Emacs. This includes a (very) brief introduction to Magit. The next post on programming and Emacs will focus much more heavily on Magit, because Magit is (as far as I can tell) the best part of Emacs when it comes to programming.
Setting Up Python
This guide assumes you have used Homebrew to install Python 3.7 and then promptly installed pyenv and pipenv. Pipenv, among other things, allows you to handle virtual environments easily, making it an excellent tool if you are working on multiple projects. Pyenv allows you to handle multiple versions of Python easily, making it an excellent tool if you are working on both modern and legacy python codebases.
Pyenv is also nice because it lets you ignore the system Python. The system Python on most computers is out of date. Even in those cases where it isn't, surprising things may depend on that system version of Python. Making sweeping changes to it can cause your computer to misbehave in subtle and unexpected ways. Whenever possible, you should leave your system Python alone, installing the minimal possible number of packages into it.
Installing Modern Python
As the guys at Podcast.__init__() and PythonBytes like to say, Python 3 is modern Python. Python 2 is legacy Python.
Legacy Python is perfectly acceptable for maintain legacy codebases, but new code should be written using the modern version of the language. As of this writing, the latest stable release is 3.7.3, with a release of 3.8.0 pending in a few months. Python 3.7 adds a lot of excellent new features, with 3.8 promising even more. Pick what you need, or what you want, but if at all possible, try to work with modern versions of the langauge. If not, you're not just missing out on new features, you could be exposing your code to bugs (especially in your 3rd party libraries) once legacy Python is no longer supported in 2020.
To get a setup similar to the one I'm running right now, run the following commands in your terminal.
brew install python3 curl https://pyenv.run | bash pyenv install 3.7.3 pyenv global 3.7.3 pip install --upgrade pip pip install pipenv
I've chosen to use pipenv
for package management for a few reasons, but the primary one is that it plays nicely with Emacs.
In order to use the linting and code completion features of Jedi, Flake8, et al, Emacs needs those libraries installed.
But I don't want those installed in the final version of code that I push out to Heroku.
pipenv
lets you have virtual environments for each project which are only activated when you ask for them via pipenv shell
or pipenv run <command>
.
That way, Emacs can leave its virtual environment with all the code linters installed active by default and I can activate the virtualenv with my project specific libraries when I test or run my code.
I'm still working on this particular workflow because it is brand new to me. In fact, as early as last week I was relying on pyenv's virtualenv features to handle this for me. So expect a more detailed writeup on this shortly.
Setting up Emacs
Before we can set up Emacs fully, we have one last command we need to run. I installed the Emacs dependencies directly into my global python (the 3.7.3 install). This is less than ideal, but it was the simplest. Should the opportunity arise later this summer, I will likely nuke my global python and try to put the Emacs dependencies into their own virtual environment.
pip install jedi flake8 autopep8 black yapf
Having installed your dependencies, it's time to set up Emacs.
elpy
Elpy is adds features to the default Python mode. Most importantly, it adds support for autocompletion via Jedi.
(use-package elpy :init (add-to-list 'auto-mode-alist '("\\.py$" . python-mode)) :custom (elpy-rpc-backend "jedi"))
Python Mode
This configures the base package for python.
Because this is a built-in, we need :ensure nil
.
(use-package python :ensure nil :mode ("\\.py" . python-mode) :config (setq python-indent-offset 4) (elpy-enable))
Company
Company is the auto-completion framework that I use. Start typing and it will attempt to auto-complete your words if you pause for a second. The current setup is very basic, but I'll be adding more to it. Specifically, I want to switch from Enter to tab to complete.
(use-package company :ensure t :defer t :diminish (company-mode . " ⓐ") :init (global-company-mode) :config (setq company-tooltip-align-annotations t company-idle-delay 0.2 ;; min prefix of 2 chars company-minimum-prefix-length 2 company-require-match nil)) (use-package company-quickhelp ; Show help in tooltip :ensure t :defer t :init (with-eval-after-load 'company (company-quickhelp-mode))) (use-package company-jedi :ensure t :defer t :init (defun enable-jedi() (setq-local company-backends (append '(company-jedi) company-backends))) (with-eval-after-load 'company (add-hook 'python-mode-hook 'enable-jedi)))
Initial Setup
After you've set this up, the very next thing you need to do is M-x jedi:install-server
.
Once you've finished this, you've got a solid Python editor in Emacs, and it took surprisingly little setup.
Follow up tutorials will cover various aspects of working with Python, but for now this is where we're starting.
Wait, that's it?
Well, right now yes. There will be more in a future week, but I literally just discovered and started working with pipenv 3 days ago. I need a little more time to flesh out my workflow there. Expect more and longer posts on Python over the following months as I explore Python and Emacs more fully.