Table of Contents
- Base Style guide
- Linting
- Formatter
- Imports
- None checks
- Getting current time in Django
- Checking if sequence is empty
- Trailing commas
- Joining Path
- Logging
- With statement
- Testing
Python Style Guide
Base Style guide
We follow Google style guide for Python. The rest of the document describes additions and clarifications.
Linting
- You can use
pylint
with this .pylintrc to check if your code passed the standard.
Formatter
- You can use yapf with this .style.yapf to avoid arguing over formatting.
- For PyCharm users, you can configure
yapf
as an external tool, see How to config Pycharm. - For VSCode users, in
setting.json
set"python.formatting.provider": "yapf",
PyCharm Configuration
YAPF can be configured as an “External Tool” inside PyCharm and run on a per-file basis. Go to File -> Settings -> Tools -> External Tools and click +. In the dialog that opens enter the following details:
- Name: YAPF
- Description: Run Yapf formatter on current file
- Program: <path to yapf>
- Arguments:
-i $FilePath$
- Working directory:
$ProjectFileDir$
<path to yapf> is the full path to the YAPF executable on your system:
- Linux/Mac:
/usr/bin/yapf
if installed with a package manager or$HOME/.local/bin/yapf
if installed with pip - Windows:
<PythonPath>\Scripts\yapf.exe
A YAPF item should now appear in the Tools -> External Tools menu. This can be bound to a shortcut key under File -> Settings -> Keymap -> External Tools.
Imports
Imports should be grouped in the following order
- standard libraries
- third party libraries
- local modules
Each group should be sorted lexicographically, ignoring case, separate by an empty line, e.g.
import collections
import queue
import sys
from absl import app
from absl import flags
import bs4
import cryptography
import tensorflow as tf
from book.genres import scifi
from myproject.backend import huxley
from myproject.backend.hgwells import time_machine
from myproject.backend.state_machine import main_loop
from otherproject.ai import body
from otherproject.ai import mind
from otherproject.ai import soul
Use import statements for packages and modules only, not for individual classes or functions. Note that there is an explicit exemption for imports from the typing module.
None checks
Always use if foo is None: (or is not None) to check for a None
# Yes
if foo is not None:
pass
# No
if foo:
pass
Getting current time in Django
Always use timezone.now()
rather than datetime.now()
import datetime
from django.utils import timezone
# Yes
now = timezone.now()
# No
now = datetime.datetime.now()
Checking if sequence is empty
For sequences, (strings, lists, tuples), use the fact that empty sequences are false
# Yes
if seq:
if not seq:
# No
if len(seq):
if len(seq) == 0:
Trailing commas
Trailing commas in sequences of items are recommended only when the closing container token ], ), or } does not appear on the same line as the final element. The presence of a trailing comma is also used as a hint to our Python code auto-formatter YAPF to direct it to auto-format the container of items to one item per line when the , after the final element is present.
# Yes
golomb3 = [0, 1, 3]
golomb4 = [
0,
1,
4,
6,
]
# No
golomb4 = [
0,
1,
4,
6
]
Joining Path
import os
# Yes
data_path = os.path.join(data_folder, "data.csv")
# No
data_path = data_folder + "/data.csv"
Logging
Prefer logging over print statement
import logging
# Yes
logger = logging.getLogger(__name__)
if bad_mojo:
logger.error('Something went wrong!')
# No
if bad_mojo:
print('Something went wrong!')
With statement
Always open file with context manager
# Yes
with open('file.txt') as file:
pass
# No
file = open('file.txt')
file.close()
For psycopg2 connection, you should use try catch over with
statement. with
statement will help commit/rollback transaction, and try catch
will help close connection.
conn = psycopg2.connect(DSN)
try:
# using with statement here, it will help commit/rollback transaction.
with conn:
with conn.cursor() as curs:
curs.execute(...)
# put another transaction here.
with conn:
with conn.cursor() as curs:
curs.execute(...)
finally:
# if you don't use connection anymore, close connection in finally block.
conn.close()
Testing
Always write unittest if you have enough time.