Stop Worrying About Python Code Formatting
An overview of the code formatter BlackJanne Kemppainen |
Wouldn't it be nice if you didn't have to worry about code formatting to make the linter happy? What if you didn't need to complain about minor formatting issues every time you are reviewing code? Can't agree on a common code style with your team so your codebase doesn't have a consistent look and feel? You are just starting a new Python project? It might be the right time to try Black.
Black is a Python code formatter which takes over your code formatting and forces consistent, deterministic and
pycodestyle abiding results with a single command. I know it sounds like I'm selling you a product but Black is free and open source and I'm writing about it because I think it's a good idea.
Every programmer has their own opinions on how code should look and inexperienced developers might not be aware of the pycodestyle recommendations. As a result the code might not be nice to look at.
Black solves these problems by forcing a certain way of formatting. It will not change the actual functionality of the code so all your bugs will still be there but at least it will make your spaghetti code look pretty! As an added benefit further changes to the code generally cause smaller diffs as Black has been optimized for that.
The minimum requirement to run Black is Python 3.6 but you can use it to analyze Python code targeting earlier versions too. Installation happens with pip:
>> python3 -m pip install black
This installs the
black command. Try that it works:
>> black No paths given. Nothing to do 😴
You can see all the available options with the
>> black --help
What does Black actually do to the code?
So what should you expect your code to look like after it has been Blackened? Here are some things that Black is doing:
- it tries to fit one simple expression on a single line if possible
- if the line is too long it will split from the outer brackets and try to fit the rest on an indented line
- if the line is still too long the same rule will be applied again with more indentation for the inner lines
- comma separated items will be split to separate lines if needed
- closing brackets are dedented
- default line length is 88 characters but it can be changed with a configuration parameter
- unnecessary vertical space is removed
- max one line of space inside functions
- spacing is added before and after functions
- trailing commas are added to comma separated expressions if they span multiple lines as it can make diffs smaller
- double quotes
"are preferred over single quotes
'unless it increases the amount of escaped quotes
- call chains (fluent API's) are delimited by the dots if needed
So as you can see Black is a little bit opinionated. But this is actually good for you because it means that you don't have to be, just accept what it's doing to your code.
You can try it out with the Black Playground.
Apart from setting the maximum allowed line length Black doesn't really give any customization options. This is an intentional choice made by the developers to make sure that the results are consistent across projects.
The absolute basic call is to just define the source files or directories and not worry about any of the other parameters. This will format all Python files that are found from the given directories or filenames.
>> black myproject
If you want to use a linge length other than the default 88 you can specify the
--line-length parameter to use some other value:
>> black -l 100 myproject
You can also use
--exclude to selectively choose which files should be affected inside directories. The parameter values should be regular expressions.
You can disable automatic formatting for a block of code by adding the code between
#fmt: off and
#fmt: on comments. This is useful for example if you want to display a multidimensional list neatly as a matrix like below:
#fmt: off identity_matrix = [ [1, 0, 0], [0, 1, 0], [0, 0, 1] ] #fmt: on
Without the magic comments the result would look like this:
identity_matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
Black can also be integrated to your code editor. You can find the instructions for your specific editor from here. Alternatively, you can also integrate Black with version control with these instructions. This will make sure that the code is formatted before committing.
Using Black in existing projects
Switching an old project to use Black can have some adverse effects. On the first run Black will probably affect a lot of lines in the code as it changes all single quotes to double quotes, for example. This can make it a bit more difficult to track the Git history of a file, depending on the amount of reformatting that was required.
The string formatting issue can be avoided with the
--skip-string-normalization parameter which will disable normalization of string quotes and prefixes. It is can also be used if the project has some existing convention that has different use cases for different quotes.
With Black you have one thing less to worry about when writing Python. At work our team is only starting to use it and after the initial tests I can see how it could keep our code more readable.
If you decied to jump to the Black bandwagon you can share your experiencess to me on Twitter. I'd like to hear your opinions on it. There are also other code formatters available so tell me if you prefer something else.