featured

By Cris EwingJanuary 23, 2014

How to get a Python IDE without the weight

Want to set up Sublime for optimal Python development?

A solid text editor is a developer’s best friend. You use it constantly and it becomes like a second pair of hands. The keyboard commands you use daily become so engrained in your muscle memory that you stop thinking about them entirely.

I’ve long been a fan of TextMate. Over the years I learned it’s corners well. I configured it just the way I wanted it to work. I grew accustomed enough to it’s foibles that I stopped paying attention to them. But the unending story of TextMate 2 finally convinced me that it was time to make a change.

The Requirements

To justify uprooting my development life so completely, I figure there are a few things I need my new editor to do:

  • It should provide excellent, configurable syntax colorization.
  • It should allow for robust tab completion.
  • It should offer the ability to jump to the definition of symbols in other files.
  • It should perform automatic code linting to help avoid silly mistakes.
  • And, as an instructor, it should be available on a wide variety of platforms so that I can help my students get it set up right.

After looking over the options I think the clear choice is Sublime Text. It is not free. In fact at $70 it’s a bit pricey. But skimping on your text editor is like putting retread tires on your high-performance car. Cheaper up front, perhaps, but with a heavy downside later.

Which Version

The first question to answer is whether to install version 2 or the new public beta version 3. The newer version offers some features around plugin support that sold me. Happily, my license purchase supports both versions, so I could downgrade without fear.

Initial Settings

Configuration in Sublime Text is done via JSON preference files. Sublime keeps copies of these in a number of places, corresponding to different levels of configuration. You can override as much or as little of the default settings as you need. And you can keep settings per-project and per-syntax too!

To create an initial set of global user-level settings use the menus to go to Preferences -> Settings - User. This starts with an empty file. You can open Preferences -> Settings - Default to see all the default settings and choose which to override.

Here are some of my choices:

{
    "color_scheme": "Packages/User/Cobalt (SL).tmTheme",
    "theme": "Soda Light 3.sublime-theme",
    "font_face": "DroidSansMonoSlashed",
    // getting older. I wonder if comfy font size increases as a linear
    //  function of age?
    "font_size": 15,
    "ignored_packages":
    [
        // I'm not a vi user, so this is of no use to me.
        "Vintage"
    ],
    "rulers":
    [
        // set text rulers so I can judge line length for pep8
        72, // docstrings
        79, // optimum code line length
        100  // maximum allowable length
    ],
    "word_wrap": false, // I hate auto-wrapped text.
    "wrap_width": 79 // This is used by a plugin elsewhere
}

Extending the Editor with Plugins

Basic setting control the way editor functions behave. But some of my requirements go beyond basic editor functions.

Sublime Text comes with a great Package Control system. It handles installing and uninstalling plugins, and even updates installed plugins for you. You can also manually install plugins that haven’t made it to the big-time yet, including ones you write yourself (using python, natch).

To install a plugin using Package Control, open the command palette with shift-super-P (ctrl-shift-P on Windows/Linux). The super key is command or on OS X. When the palette opens, typing install will bring up the Package Control: Install Package command. Hit enter to select it.

The Command Palette

After you select the command, Sublime Text fetches an updated list of packages from the network. It might take a second or two for the list to appear. When it does, start to type the name of the package you want. Sublime Text filters the list and shows you what you want to see. To install a plugin, select it with the mouse, or use arrow keys to navigate the list and hit enter when your plugin is highlighted.

The Plugin List

My Plugins

Autocompletion

The first item on my list not completely satisfied by the core editor is tab completion. By default, Sublime Text will index symbols in open files and projects, but that doesn’t cover installed python packages that may be part of a non-standard run environment. I want more.

There are two contenders for the crown for this plugin: SublimeCodeIntel and SublimeJedi. The former offers the advantage of supporting sub-packages for a wide variety of languages. But I was unable to get it to work reasonably well. In the very large Plone projects I work on, it never managed to complete building an index.

I decided instead to try SublimeJedi. It’s limited to python completions, but that is 90% of my code work, so I’m okay with the restriction for now. It’s powered by the Jedi code completion package, which is native Python as well.

Once I installed the package using Package Control, all I had to do was to add a few settings to tell it where to look for code. I can make global settings, but I can also set this per-project! For example, here are the settings from a large Plone project I’m working on at the moment (they appear in <project_name>.sublime-project):

{
    "folders":
    [
        // ...
    ],

    "settings": {
        // ...
        "python_interpreter_path": "/Users/cewing/pythons/python-2.7/bin/python",

        "python_package_paths": [
            "/path/to/project/buildout/parts/omelette"
        ]
    }
}

This ensures that the executable python used is the same as the one used for my project code, and ensures that all the extra python packages in my buildout will be indexed properly. Once that’s over, I have nifty autocompletion over all the defined symbols in my code base

Autocompletion In Action

Beyond that, the SublimeJedi plugin also supports jumping to the definition of a symbol in my code. By pressing ctrl-shift-G while my cursor is in a symbol, I can immediately open the file where that symbol was defined. I can even use alt-shift-F to find other usages of the same symbol elsewhere in my code. Nice!

Code Linting

Code linting can show you mistakes you’ve made in your source before you attempt to run the code. This saves time. Sublime Text has an available plugin for code linters called SublimeLinter. SublimeLinter is a kind of meta-plugin, providing a framework into which you can plug specific linters for various languages.

Python has a couple of great tools available for linting, the pep8 and pyflakes packages. Pep8 checks your code for style violations, lines too long, extra spaces and so on. Pyflakes checks for syntactic violations, like using a symbol that isn’t defined or importing a symbol you don’t use.

There’s another Python package out there, flake8, which wraps both of these and combines them with a tool to check the cyclomatic complexity of your code, mccabe.

There is a nice plugin for the SublimeLinter that utilizes flake8. To install it, you must first install the Python package it requires. I do this with a virtualenv. First, I create a virtualenv and activate it:

$ cd /Users/cewing/virtualenvs
$ python virtualenv.py sublenv
New python executable in sublenv/bin/python
Installing setuptools, pip...done.
$ source sublenv/bin/activate
(sublenv)$

Once that is accomplished, I can use Python packaging tools to install the dependency package:

(sublenv)$ pip install flake8
Downloading/unpacking flake8
[...]
Downloading/unpacking pyflakes>=0.7.3 (from flake8)
[...]
Downloading/unpacking pep8>=1.4.6 (from flake8)
[...]
Downloading/unpacking mccabe>=0.2.1 (from flake8)
[...]
Installing collected packages: flake8, pyflakes, pep8, mccabe
[...]
Successfully installed flake8 pyflakes pep8 mccabe
Cleaning up...
(sublenv)$

Now, I have flake8 and its dependencies all ready for me. The Python executable they are associated with is in /Users/cewing/virtualenvs/sublenv/bin as are the executable files each add-on provides:

(sublenv)$ ls sublenv/bin
activate            easy_install-2.7    pip2.7
activate.csh        flake8              pyflakes
activate.fish       pep8                python
activate_this.py    pip                 python2
easy_install        pip2                python2.7

At this point, I can install SublimeLinter and then SublimeLinter-flake8 using Package Control. To make it all work, all I have to do is add a few settings to Preferences -> Package Settings -> SublimeLinter -> Settings - User:

{
    //...
    "linters": {
        "flake8": {
            "@disable": false,
            "args": [],
            "builtins": "",
            "excludes": [],
            "ignore": "",
            "max-complexity": 10,
            "max-line-length": null,
            "select": ""
        }
    },
    //...
    "paths": {
        "linux": [],
        "osx": [
            "/Users/cewing/virtualenvs/sublenv/bin"
        ],
        "windows": []
    },
    "python_paths": {
        "linux": [],
        "osx": [
            "/Users/cewing/virtualenvs/sublenv/bin"
        ],
        "windows": []
    },
    //...
}

The The paths key points to the path that contains my flake8 executable. The python_paths points to the location of the python executable to be used. These both point to the virtualenv location I set up earlier. The settings inside the flake8 object allow me to control the performance of the linter. I can choose to ignore certain errors, set a custom maximum line length, adjust what counts as “too complex” for me. It’s all very configurable and nice. And the output looks pretty good too:

Flake8 Output

White Space Management

One of the issues highlighted by flake8 is trailing spaces. Sublime text provides a setting that allows you to remove them every time you save a file:

{
    "trim_trailing_whitespace_on_save": true
}

There’s a problem with this, though. If you work on a team where someone does not use such a plugin, there can be a lot of trailing whitespace in files you are editing. Deleting them all at once creates a lot of noise in changesets.

I prefer to keep my commits for things like whitespace cleanup separate from those that make changes to code. So I’ve installed a plugin that can help, TrailingSpaces. With this plugin installed via the Package Manager I gain access to two settings:

{
    //...
    "trailing_spaces_modified_lines_only": true,
    "trailing_spaces_trim_on_save": true,
    // ...
}

These allow me to trim whitespace on save, but only on lines I’ve modified. That way, if I want to trim all whitespace, I can do it manually and keep my code changesets free of noise.

Wrap-Up

Changing editors is a big step for a developer. But if you make the right choices and spend the time to configure it well, your new editor can really shine.

I’m sad to leave TextMate behind, but in Sublime Text I’ve got a tool to last me for the next long haul. It’s got great colorization, tab completion and symbol resolution, automatic linting and is completely cross platform, so I can teach it to my students and share the joy.