Cleaning Your Django Project With PyLint And Buildbot

Cleaning by inf3ktionThere are a number of tools for checking whether your Python code meets a coding standard. These include, PyChecker and PyLint. Of these, PyLint is the most comprehensive and is the tool which I prefer to use as part of my buildbot checks that run on every commit.

PyLint works by parsing the Python source code itself and checking things like using variables that aren’t defined, missing doc strings and a large array of other checks. A downside of PyLint’s comprehensiveness is that it runs the risk of generating false positives. As it parses the source code itself it struggles with some of Python’s more dynamic features, in particular metaclasses, which, unfortunately, are a key part of Django. In this post I’ll go through the changes I make to the standard PyLint settings to make it more compatible with Django.


This line disables a few problems that are picked up entirely. W0403 stops relative imports from generating a warning, whether you want to disable these or not is really a matter of personal preference. Although I appreciate why there is a check for this, I think this is a bit too picky. W0232 stops a warning appearing when a class has no __init__ method. Django models will produce this warning, but because they’re metaclasses there is nothing wrong with them. Finally, E1101 is generated if you access a member variable that doesn’t exist. Accessing members such as id or objects on a model will trigger this, so it’s simplest just to disable the check.


These makes the output of PyLint easier to parse by Buildbot, if you’re not using it then you probably don’t need to include these lines.

good-names= ...,qs

Apart from a limited number of names PyLint tries to enforce a minimum size of three characters in a variable name. As qs is such a useful variable name for a QuerySet I force this be allowed as a good name.


The last change I make is to allow much longer lines. By default PyLint only allows 80 character long lines, but how many people have screens that narrow anymore? Even the argument that it allows you to have two files side by side doesn’t hold water in this age where multiple monitors for developers are the norm.

PyLint uses the exit code to indicate what errors occurred during the run. This confuses Buildbot which assumes that a non-zero return code means the program failed to run, even when using the PyLint buildstep. To work around this I use a simple management command to duplicate the pylint program’s functionality but that doesn’t let the return code propagate back to Builtbot.

from import BaseCommand

from pylint import lint

class Command(BaseCommand):
    def handle(self, *args, **options):
        lint.Run(list(args + ("--rcfile=../pylint.cfg", )), exit=False)

Photo of Cleaning by inf3ktion.


Author: Andrew Wilkinson

I'm a computer programmer and team leader working at the UK grocer and tech company, Ocado Technology. I mostly write multithreaded real time systems in Java, but in the past I've worked with C#, C++ and Python.

3 thoughts on “Cleaning Your Django Project With PyLint And Buildbot”

  1. Thanks for the tips! Put me on the list of people who still prefer 80 columns; my second monitor is in portrait mode and with a file browser and taglist open on either side, I get about 100 columns of text for code display. It’s also easier to scan and navigate shorter lines.

  2. 80 columns please!!

    People who don’t use IDE but use hard core editors like vim, jed, emacs, etc. often have one terminal or terminal screen for the editor and one for the unit test runner or a development server running side by side.

    Another very real argument for 80 characters is readability. Code is supposed to be read from top to bottom or bottom to top. Like a parser/compiler sort of. When you’re then reading and sporadically have to track your attention away to the side the code becomes harder to read.

    A third very real argument for 80 characters is that if you allow your code to grow too much horizontally, perhaps huge control flows need to be refactored into functions or new classes.

    1. All your arguments make sense, and I do keep my lines as short as possible. What I don’t do is keep to a hard limit of 80 columns. Sometimes I think it’s clearer to have a function call on one line, even though it might be 85 or 90 characters long. If you’re hitting 80 columns because of nested ifs or for loops then your code definitely needs to be refactored.

      I think it’s important to only get PyLint to alert to the more serious problems with the code, otherwise you’ll be overwhelmed with changes that need to be made.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s