2.4 Advanced Linting Features
Last updated on 2025-05-09 | Edit this page
Overview
Questions
- What can I do to increase the detail of Pylint reports?
- How can I reduce unwanted messages from Pylint?
- How can I use static code analysis tools with VSCode?
Objectives
- Use Pylint to produce a verbose report showing number of occurrences of encountered message types
- Fix an issue within our code to increase our Pylint score
- Specify message types to Pylint that we don’t want reported
- Install a Pylint extension into VSCode
More Verbose Reporting
We can also obtain a more verbose report by adding
--reports y
to the command, which gives us a lot more
detail:
Here’s a part of that output:
OUTPUT
...
Messages
--------
+---------------------------+------------+
|message id |occurrences |
+===========================+============+
|redefined-outer-name |4 |
+---------------------------+------------+
|invalid-name |4 |
+---------------------------+------------+
|missing-function-docstring |2 |
+---------------------------+------------+
|unused-import |1 |
+---------------------------+------------+
|unspecified-encoding |1 |
+---------------------------+------------+
|superfluous-parens |1 |
+---------------------------+------------+
|missing-module-docstring |1 |
+---------------------------+------------+
|consider-using-with |1 |
+---------------------------+------------+
...
QUESTION: for those doing activity, who’s managed to run this command? YES/NO
It gives you some overall statistics, plus comparisons with the last time you ran it, on aspects such as:
- How many modules, classes, methods and functions were looked at
- Raw metrics (which we’ll look at in a minute)
- Extent of code duplication (none, which is good)
- Number of messages by category (again, we can see that it’s mainly convention issues)
- A sorted count of the messages we received
Looking at raw metrics, we can see that it breaks down our program into how many lines are code lines, python docstrings, standalone comments, and empty lines. This is very useful, since it gives us an idea of how well commented our code is. In this case - not very well commented at all! For normal comments, the usually accepted wisdom is to add them to explain why you are doing something, or perhaps to explain how necessarily complex code works, but not to explain the obvious, since clearly written code should do that itself.
Increasing our Pylint Score - Adding a Docstring
QUESTION: Who’s familiar with Python docstrings? Yes/No
Docstrings are a special kind of comment for a function, that explain what the function does, the parameters it expects, and what is returned. You can also write docstrings for classes, methods, and modules, but you should usually aim to add docstring comments to your code wherever you can, particularly for critical or complex functions.
Let’s add one to our code now, within the
fahr_to_celsius
function.
PYTHON
"""Convert fahrenheit to Celsius.
:param fahr: temperature in Fahrenheit
:returns: temperature in Celsius
"""
Re-run pylint - can see we have one less docstring error, and a slightly higher score.
If you’d like to know more about docstrings and commenting, there’s an in-depth RealPython tutorial on these and the different ways you can format them.
Ignoring Issues
We can instruct pylint to ignore any particular types of issues, which is useful if they are not seen as important or pedantic, or we need to see other types more clearly. For example, to ignore any unused imports:
Or, to disable all issues of type “warning”:
This can be particularly useful if we wish to ignore particularly pedantic rules, such as long line lengths over 100 characters.
Challenge
Edit the climate_analysis.py
file and add in a comment
line that exceeds 100 characters. Then re-run pylint and determine the
issue identifier for this message, and re-run pylint again disabling
this specific issue.
OUTPUT
************* Module climate_analysis
climate_analysis.py:3:0: C0301: Line too long (111/100) (line-too-long)
climate_analysis.py:17:0: C0325: Unnecessary parens after '=' keyword (superfluous-parens)
climate_analysis.py:1:0: C0114: Missing module docstring (missing-module-docstring)
...
We can see that the identifier is C0301
, so:
However, if we wanted to ignore this issue for the foreseeable future, typing this in every time would be tiresome. Fortunately we can specify a configuration file to pylint which specifies how we want to interpret issues.
We do this by first using pylint to generate a default
.pylintrc
file. It directs this as output to the shell, so
we need to redirect it to a file to capture it. Ensure you are in the
repository root directory, then:
If you edit this generated file you’ll notice there are many things
we can specify to pylint. For now, look for disable=
and
add C0301
to the list of ignored issues already present
that are separated by commas, e.g.:
# no Warning level messages displayed, use "--disable=all --enable=classes
# --disable=W".
disable=C0301,
raw-checker-failed,
bad-inline-option,
locally-disabled,
file-ignored,
suppressed-message,
useless-suppression,
deprecated-pragma,
use-implicit-booleaness-not-comparison-to-string,
use-implicit-booleaness-not-comparison-to-zero,
use-symbolic-message-instead
Every time you re-run it now, the C0301
issue will not
be present.
Using Pylint within VSCode
The good news is that if you’re using the VSCode IDE, we can also (or
alternatively) install a Python linter in VSCode to give us this code
analysis functionality, by installing a pylint extension. Select the
Extensions
icon and this time search for
Pylint
, the one by Microsoft, and click
Install
.
Going back to our code you should now find lots of squiggly underlines of various colours.
I don’t see any Squiggly Underlines!!
If you happen to not see any squiggly underlines in the editor, it
could be the linter extension hasn’t looked at your code yet. In order
to trigger the linter to show us further issues, try saving the file to
trigger the linter to do this. So go to File
then
Save
on the menu bar, and you should now see a lot of
squiggly underlines in the code.
These squiggly lines indicate an issue, and by hovering over them, we
can see details of the issue. For example, by hovering over the
variables shift
or comment
- we can see that
the variable names don’t conform to what’s known as an
UPPER_CASE
naming convention. Simply, the linter has
identified these variables as constants, and typically, these are in
upper case. We should rename them, e.g. SHIFT
and
COMMENT
. But following this, we also need to update the
reference to comment
in the code so it’s also upper case.
Now if we save the file selecting File
then
Save
, we should see the linter rerun, and those highlighted
issues disappear.
We can also see a comprehensive list of all the issues found, by
opening a code Problems
window. In the menu, go to
View
then Problems
, and then you’ll see a
complete list of issues which we can work on displayed in the pane at
the bottom of the code editor. We don’t have to address them, of course,
but by following them we bring our code style closer to a commonly
accepted and consistent form of Python.
Summary
Code linters like pylint help us to identify problems in our code, such as code styling issues and potential errors, and importantly, if we work in a team of developers such tools help us keep our code style consistent. Attempting to understand a code base which employs a variety of coding styles (perhaps even in the same source file) can be remarkably difficult.
But there are some aspects we should be careful of when using linters and interpreting their results:
- They don’t tell us that the code actually works and they don’t tell us if the results our code produces are actually correct, so we still need to test our code.
- They don’t give us any Idea of whether it’s a good implementation, and that the technical choices are good ones. For example, this code contains functions to conduct temperature conversions, but it turns out there’s a number of well-maintained Python packages that do this (e.g. pytemperature)so we should be using a tried and tested package instead of reinventing the wheel.
- They also don’t tell us if the implementation is actually fit for purpose. Even if the code is a good implementation, and it works as expected, is it actually solving the intended problem?
- They also don’t tell us anything about the data the program uses which may have its own problems.
- A high score or zero warnings may give us false confidence. Just because we have reached a 10.00 score, doesn’t mean the code is actually good code, just that it’s likely well formatted and hopefully easier to read and understand.
So we have to be a bit careful. These are all valid, high-level questions to ask while you’re writing code, both as a team, and also individually. In the fog of development, it can be surprisingly easy to lose track of what’s actually being implemented and how it’s being implemented. A good idea is to revisit these questions regularly, to be sure you can answer them!
However, whilst taking these shortcomings into account, linters are a very low effort way to help us improve our code and keep it consistent.
Key Points
- Use the
--reports y
argument on the command line to Pylint to provide verbose reports - Instruct Pylint to ignore messages on the command line using the
--disable=
argument followed by comman-separated list of message identifiers - Use
pylint --generate-rcfile > .pylintrc
to generate a pre-populated configuration file for Pylint to edit to customise Pylint’s behaviour when run within a particular directory - Pylint can be run on the command line or used within VSCode
- Using Pylint helps us keep our code consistent, particularly across teams
- Don’t use Pylint feedback and scores as the only means to judge code quality