Standardize your Python
A little background: I've been a Python developer for just over 5 years. I started off as a web developer, and have transitioned into an operational data scientist in the past couple of years.
I really enjoy programming in Python. I enjoyed learning it on my own, and teaching some Python-based intro-to-programming classes in my previous life as a High School teacher.
One of the wonderful things about Python is the many different ways that it can be written and used. Just the fact that I was able to transition from web development to data science within the same language is a testament to that fact. Different development styles can be used – just writing scripts meant to be run individually, or a whole suite of modules and classes to be imported and integrated together.
But, one of the frustrating things in working with a team of developers is having to work with other programmer's styles. Here are a few tips for standardizing your team's Python code.
You can follow along in the examples by pulling the code from https://github.com/blackary/standardization
In this post, I want to give a brief introduction to some of the guides and tools which I have found useful for standardizing Python on the teams I've worked on.
PEP 8
The most famous of the PEPs (Python Enhancement Proposals), PEP 8 describes the official style guidelines which should be followed when writing Python code. Even just having everyone on your team read through this document can be a great first step in standardizing your style. If you have disagreements with some parts, and think some pieces will be different, that's OK. Start with PEP 8 and tweak what you want to tweak (or ignore what you want to ignore) as a team, and run with it. Or just use it to start a discussion about how you as a team want to style your code.
flake8
One of the first difficulties in actually applying PEP 8 is that there is a lot to remember. It would be nice to have some automated way to check and see if you're actually following the style rules. Enter flake8.
Flake8 is. a linter, which checks your code for PEP 8 style conventions, and also various common mistakes (like importing a library but not using it), Syntax Errors, etc.
For example, given the following code in bad.py:
a= "way waywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywaywayway too long of a line"
import something_unused
6 = x
y = [1,2, 3,
4,
5]
Running flake8 bad.py returns the following errors:
$ flake8 bad.py
bad.py:1:2: E225 missing whitespace around operator
bad.py:1:80: E501 line too long (160 > 79 characters)
bad.py:3:1: E402 module level import not at top of file
bad.py:5:1: E999 SyntaxError: cannot assign to literal
bad.py:7:7: E231 missing whitespace after ','
bad.py:8:9: E127 continuation line over-indented for visual indent
bad.py:9:1: E128 continuation line under-indented for visual indent
This can be run manually as above, but is even more useful if it's run automatically. For example, when you commit code to a repository, through a pre-commit hook, or it can be installed as a plug-in on your editor (VS Code, vim, etc.), to add underlines around code which violates styles guides or has a syntax error.

But, what about cases where PEP 8 has multiple valid formatting options? Enter Black.
Black
What should you do when there are disagreements which both fit within the PEP 8 guide? In particular, things like where to place closing brackets or braces, single-vs-double quotes, etc. Black is a Python formatter which is very opinionated, and takes a stand even on cases where PEP 8 leaves several options open.
Here is an example from PEP 8 itself of multiple valid styles:
import some_function_that_takes_arguments
my_list = [
1, 2, 3,
4, 5, 6,
]
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
result = some_function_that_takes_arguments(
'a', 'b', 'c',
"d", "e", "f",
)
flake8 valid_options.py yields no output, signaling that this is valid code as far as Flake8 is concerned. However, running it through Black shows how it would be reformatted. Just running black {filename} would actually reformat the file in-place, so for demonstration sake, I will use black - which takes code in from standard input and writes to standard output the resulting reformatted result.
$ cat valid_options.py | black -
my_list = [
1,
2,
3,
4,
5,
6,
]
my_list = [
1,
2,
3,
4,
5,
6,
]
result = some_function_that_takes_arguments("a", "b", "c", "d", "e", "f",)
result = some_function_that_takes_arguments("a", "b", "c", "d", "e", "f",)
reformatted -
All done! ✨ 🍰 ✨
1 file reformatted.
Any code that has been formatted by Black should also successfully pass the flake8 test.
Just like flake8, Black can be run as a command-line function, installed as an editor plugin (VS Code, vim, etc.) or through a pre-commit hook.
Conclusion
I hope these tools are helpful for you in creating more consistent code for you and your team.