Format Python however you like with Black

Learn more about solving common Python problems in our series covering seven PyPI libraries.
296 readers like this.
OpenStack source code (Python) in VIM

Alex Sanchez. CC BY-SA 4.0.

Python is one of the most popular programming languages in use today—and for good reasons: it's open source, it has a wide range of uses (such as web programming, business applications, games, scientific programming, and much more), and it has a vibrant and dedicated community supporting it. This community is the reason we have such a large, diverse range of software packages available in the Python Package Index (PyPI) to extend and improve Python and solve the inevitable glitches that crop up.

In this series, we'll look at seven PyPI libraries that can help you solve common Python problems. In the first article, we learned about Cython; today, we'll examine the Black code formatter.

Black

Sometimes creativity can be a wonderful thing. Sometimes it is just a pain. I enjoy solving hard problems creatively, but I want my Python formatted as consistently as possible. Nobody has ever been impressed by code that uses "interesting" indentation.

But even worse than inconsistent formatting is a code review that consists of nothing but formatting nits. It is annoying to the reviewer—and even more annoying to the person whose code is reviewed. It's also infuriating when your linter tells you that your code is indented incorrectly, but gives no hint about the correct amount of indentation.

Enter Black. Instead of telling you what to do, Black is a good, industrious robot: it will fix your code for you.

To see how it works, feel free to write something beautifully inconsistent like:

def add(a, b): return a+b

def mult(a, b):
      return \
        a              *        b

Does Black complain? Goodness no, it just fixes it for you!

$ black math 
reformatted math
All done! ✨ ? ✨
1 file reformatted.
$ cat math 
def add(a, b):
    return a + b


def mult(a, b):
    return a * b

Black does offer the option of failing instead of fixing and even outputting a diff-style edit. These options are great in a continuous integration (CI) system that enforces running Black locally. In addition, if the diff output is logged to the CI output, you can directly paste it into patch in the rare case that you need to fix your output but cannot install Black locally.

$ black --check --diff bad 
--- math 2019-04-09 17:24:22.747815 +0000
+++ math 2019-04-09 17:26:04.269451 +0000
@@ -1,7 +1,7 @@
-def add(a, b): return a + b
+def add(a, b):
+    return a + b
 
 
 def mult(a, b):
-          return \
-                  a             *             b
+    return a * b
 
would reformat math
All done! ? ? ?
1 file would be reformatted.
$ echo $?
1

In the next article in this series, we'll look at attrs, a library that helps you write concise, correct code quickly.

What to read next
Tags
Moshe sitting down, head slightly to the side. His t-shirt has Guardians of the Galaxy silhoutes against a background of sound visualization bars.
Moshe has been involved in the Linux community since 1998, helping in Linux "installation parties". He has been programming Python since 1999, and has contributed to the core Python interpreter. Moshe has been a DevOps/SRE since before those terms existed, caring deeply about software reliability, build reproducibility and other such things.

3 Comments

Is there any way to configure the style that black uses?

For example, the number of space it uses for each indentation level? Also I really, really dislike defs and function calls with no space before the opening parenthesis.

Nearly 40 years ago when I was writing PL/1 on a Multics system, there was a programmed called format_pl1 which used a specific comment at the head of the source code for customising the format.

Have we learned nothing?

I read the documentation and it has # fmt: off and # fmt: on to exclude those cases where you just need to preserve formatting, so I _could_ live with it.

Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.