One class of productivity tools that can be used to support the development of code that conforms to a particular style guide or coding convention such as PEP8 are known as code linters.
These tools provide offline, static analysis of code and can generate reports that describe where code diverges from the style guide.
Some tools may also automatically correct code style, although from a learning perspective it can often be more useful to be warned when you diverge from the code style guidelines so that you can fix the code (and learn how to write it correctly) rather than having the code style automatically corrected for you.
The pycodestyle_magic extension provides some IPython magic for automatically running the flake8
PEP8 linter against code cells each time you run them.
If your code diverges from PEP8 style guidelines, a warning will be issued.
Install the package by running the following command, which also installs some additional linting rules, such as rules covering function name styling and docstrings.
%%capture
!pip install --user flake8 pycodestyle pycodestyle_magic
#Install additional style convention rules
!pip install --user pep8-naming flake8-bugbear flake8-docstrings flake8-builtins
# Provide additional conventions for pandas code: https://github.com/deppen8/pandas-vet
!pip install --user pandas-vet
To disable rules associated with a particular flake8
extension package, uninstall it and then restart the notebook kernel. For example:
!pip uninstall -y flake8-bugbear
Other flake8
extensions can be found in this awesome list of flake8
extensions.
Each time you want to run the linter, you need to load the magic into a notebook using the command:
%load_ext pycodestyle_magic
Alternatively, you can modify the startup file that is loaded in to each notebook to automatically load the magic into every notebook. Run the following cell to update the startup file:
!echo "\n%load_ext pycodestyle_magic\n" >> /home/oustudent/.ipython/profile_default/startup/tm351_start.ipy
The linter can be enabled within a particular notebook by running the magic command:
%flake8_on
With the linter enabled, each time you run a code cell the code within it will be passed through the linter, and any deviations from the flake installed style conventions will be reported on.
If you want the automatic linter to be enabled automatically for each notebook, add the flake8_on
command to the notebook startup file:
echo "\nflake8_on\n" >> /home/oustudent/.ipython/profile_default/startup/tm351_start.ipy
Automatic running of the linter within a notebook can be disabled by using the command: %flake8_off
Note that if you have turned flake8_on
several times in the same notebook, you need to run %flake8_off
the same number of times to disable it.
Note that the linter is run against the complete contents of every code cell, so if you include IPython command line directives (lines prefixed with a !
that execute code on the command line), these lines are likely to raise warnings.
! echo "hello"
As the linter is applied to the complete contents of a code cell, to prevent the linter being applied to a particular cell, you need to run %flake8_off
in the cell before it, and then enable %flake8_on
again at the end of the cell you want to run without linting.
%flake8_off
! echo "hello"
%flake8_on
The following code cells contain examples code that will generate style guide warnings.
Note that the doctring warning D100 will be raised in each code cell because the code cell it treated as a Python module and the style guide requires it to be prefixed with docstring. Hopefully, a way of disabling certain warnings will be provided in a future version of the magic.
a=1
b = [1,2,3]
map = None
Correctly formatted code should have whitespace around the operator and after each ,
in the list. Any variable names that clash with Python reserved words are warned against.
a = 1
b = [1, 2, 3]
my_map = None
Several style conventions are associate with function definitions, including function naming and the requirement for a correctly styled docstring:
def myFunction(txt):
a=1
print(txt)
return
Note that unused arguments are identified and warned about.
A well formatted function takes the following form:
def my_function(txt):
"""Print a simple annotated message and return a number."""
a = 1
print(txt)
return a
Several tools are available that can be used to repair unstyled code, where possible:
One such tool is provided by the Python autopep8
package. An autopep8
extension is provided as part of the jupyter_contrib_nbextensions
package but it requires the installation of the autopep8
dependency to work:
%%capture
!pip install --user autopep8
#Enable the extension
!jupyter nbextension enable code_prettify/autopep8
The autopep8
extension configurator can be found here: code_prettify/autopep8.
Reload the notebook to see the enabled toolbar button (a hammer).
When a code cell such as the following code cell is selected, clicking the toolbar button will repair the code styling insofar as such repairs are possible.
def myFunction(txt):
a=1
print(txt)
return
Additional tools, including ones that run automatically, will be described in another document.
Whilst automatic code styling support tools are undoubtedly useful, when learning good practice it can often be more useful — if not also slightly more annoying! — to receive a warning each time you do make a stylistic error.