Python Coding Guidelines¶
Black¶
Run Black on every commit. https://black.readthedocs.io/en/stable/
Import Order¶
Run import sorter on every commit.
Sorter should work in the following way:
group imports in order by
standard library
3rd party libraries
your own libraries
app local libraries
package local imports
Helps you to skim quickly through what is imported.
sort those alphabetically
This builds upon 1 and usually gives a nice shape to the import lines.
always import a single object
Makes diffs easier to read (even if you have –word-diff) and eliminates some merge conflicts.
Pragma markup to except an import from the sorting order. This is necessary because while module imports SHOULD not effect global state of the process in any way other than adding the module into the local scope of the import. They MAY have side effects either by defect or by necessity 1.
Example:
import functools
from functools import partial
import os
import os.path
from twisted.internet.defer import Deferred
from twisted.internet.defer import inlineCallbacks
from twisted.internet import reactor
from mylib import foo
from myapp import session
from .model import BussinessThing
The last three here may be in single group since there is so few in each block but as the blocks grow it may be preferable to separate like this. Use judgement.
Wild Card Import Considered Harmful¶
https://docs.python.org/3/reference/simple_stmts.html#the-import-statement
from foo import *
It is only marginally useful in some niche use cases.
It risks identifier shadowing. Consider this:
import foo
import bar
assert foo.A is not bar.A
from foo import A
from bar import A
assert A is bar.A and A is not foo.A
It is generally better to just disallow by linter policy.
Stop Writing Custom Logging Initializers¶
logging
has fairly sane declarative config which you need to just load via
dictConfig
and you are done.
In the code you will get loggers via logging.getLogger(__name__)
. There is mostly no need to
write wrappers around the getLogger
.
It is way too common to see code bases which turn these one-liners into tens to hundreds of lines of code with no added benefit. Even worse, these custom initializers usually bring more dependencies which complicate or even entirely prevent the use of REPL to run simple tests within the runtime of the project.