Get the highlights in your inbox every week.
Pylint: Making your Python code consistent | Opensource.com
Pylint: Making your Python code consistent
Pylint is your friend when you want to avoid arguing about code complexity.
Pylint is a high-level Python style enforcer. While flake8 and black will take care of "local" style: where the newlines occur, how comments are formatted, or find issues like commented out code or bad practices in log formatting.
Pylint is extremely aggressive by default. It will offer strong opinions on everything from checking if declared interfaces are actually implemented to opportunities to refactor duplicate code, which can be a lot to a new user. One way of introducing it gently to a project, or a team, is to start by turning all checkers off, and then enabling checkers one by one. This is especially useful if you already use flake8, black, and mypy: Pylint has quite a few checkers that overlap in functionality.However, one of the things unique to Pylint is the ability to enforce higher-level issues: for example, number of lines in a function, or number of methods in a class.
These numbers might be different from project to project and can depend on the development team's preferences. However, once the team comes to an agreement about the parameters, it is useful to enforce those parameters using an automated tool. This is where Pylint shines.
In order to start with an empty configuration, start your
This disables all Pylint messages. Since many of them are redundant, this makes sense. In Pylint, a
message is a specific kind of warning.
You can check that all messages have been turned off by running
$ pylint <my package>
In general, it is not a great idea to add parameters to the
pylint command-line: the best place to configure your
pylint is the
.pylintrc. In order to have it do something useful, we need to enable some messages.
In order to enable messages, add to your
.pylintrc, under the
For the "messages" (what Pylint calls different kinds of warnings) that look useful. Some of my favorites include
too-many-branches. All of those limit complexity of modules or functions, and serve as an objective check, without a human nitpicker needed, for code complexity measurement.
A checker is a source of messages: every message belongs to exactly one checker. Many of the most useful messages are under the design checker. The default numbers are usually good, but tweaking the maximums is straightfoward: we can add a section called
DESIGN in the
Another good source of useful messages is the
refactoring checker. Some of my favorite messages to enable there are
stop-iteration-return (which looks for generators which use
raise StopIteration when
return is the correct way to stop the iteration). and
chained-comparison, which will suggest using syntax like
1 <= x < 5 rather than the less obvious
1 <= x && x > 5
Finally, an expensive checker, in terms of performance, but highly useful, is
similarities. It is designed to enforce "Don't Repeat Yourself" (the DRY principle) by explicitly looking for copy-paste between different parts of the code. It only has one message to enable:
duplicate-code. The default "minimum similarity lines" is set to
4. It is possible to set it to a different value using the
Pylint makes code reviews easy
If you are sick of code reviews where you point out that a class is too complicated, or that two different functions are basically the same, add Pylint to your Continuous Integration configuration, and only have the arguments about complexity guidelines for your project once.