Pythonistaが唯一守らなければいけないルールはPEP8コーディング規約だと思う。初心者であれば特に変な癖が付く前にエディタにPEP8をチェックするプラグインを導入すべきだ。PEP8違反が多いコードとバグや問題が多発するコードは明らかに相関がある。本エントリではPEP8規約に沿ったコードか確認ツールの導入方法、有名ライブラリのPEP8規約準拠割合、各エディタ毎のPEP8ツールを紹介していく。
PythonではPEP20 - The Zen of Python(日本語訳)にて次の通り心構えを掲げています。
読みやすいことは善である。特殊であることはルールを破る理由にならない。しかし、実用性を求めると自然さが失われることがある。
無理してPEP8違反ゼロを目指す必要はありませんが、出来る限りPEP8に準拠する統一した読みやすいコードを書いって欲しいです。どの程度の違反が許容範囲なのかは、下部のPyPiランキング上位ライブラリの違反状況で一覧にしてみました。よろしくお願いします。
プロジェクトのPEP8違反を発見する
flake8を利用すると、PEP8準拠状況を簡単に確認できます。
pip install flake8
flake8 {project_root} --filename=*.py --exclude=commands,migrations,[^_]*.py --max-line-length=79
xxxxxx.py:20:1: E101 indentation contains mixed spaces and tabs
xxxxxx.py:20:1: W191 indentation contains tabs
xxxxxx.py:20:9: E223 tab before operator
xxxxxx.py:20:14: E261 at least two spaces before inline comment
xxxxxx.py:21:1: W191 indentation contains tabs
xxxxxx.py:21:8: E223 tab before operator
xxxxxx.py:21:13: E261 at least two spaces before inline comment
xxxxxx.py:22:1: W191 indentation contains tabs
xxxxxx.py:22:10: E223 tab before operator
xxxxxx.py:22:14: E261 at least two spaces before inline comment
xxxxxx.py:23:1: W191 indentation contains tabs
xxxxxx.py:23:9: E223 tab before operator
# 1行毎にPEP8違反しているコードに遭遇すると戦慄が走る
PyPiランキング上位の有名ライブラリのPEP8違反状況
PEP8違反はどのくらいが適切なのか、PyPi Rankingでダウンロード数上位50プロジェクトに対して調査してみました。1行あたり平均0.1以下のPEP8違反であれば優秀なプロジェクトと言えるのではないでしょうか。経験上PEP8の存在を知らないPython初心者は1行あたり0.3を超えるコードを書くことが多いです。
# -*- coding:utf-8 -*-
from __future__ import absolute_import, unicode_literals
import os
import commands
pypi_ranking = [
'simplejson',
'setuptools',
'requests',
'distribute',
'virtualenv',
'six',
'pip',
'certifi',
'boto',
'wincertstore',
'pbr',
'python-dateutil',
'nose',
'Jinja2',
'lxml',
'docutils',
'MarkupSafe',
'pyasn1',
'pytz',
'PyYAML',
'pycrypto',
'pika',
'rsa',
'coverage',
'colorama',
'Django',
'psycopg2',
'botocore',
'cffi',
'awscli',
'paramiko',
'jmespath',
'pycparser',
'SQLAlchemy',
'ecdsa',
'redis',
'selenium',
'bcdoc',
'supervisor',
'Werkzeug',
'mock',
'zc.buildout',
'httplib2',
'Paste',
'Flask',
'pep8',
'pymongo',
'carbon',
'ssl',
'meld3',
]
def get_py_file_line_count(_dir):
_cmd_base = 'find {} -name \*.py|xargs wc -l'
cmd = _cmd_base.format(_dir)
result = commands.getoutput(cmd)
return int(result.split('\n')[-1].replace(' total', ''))
def get_flake8_warning(_dir):
cmd_base = 'flake8 {} --filename=*.py --exclude=commands,migrations,[^_]*.py ' \
'--max-line-length=79|wc -l'
cmd = cmd_base.format(_dir)
return int(commands.getoutput(cmd))
# pip install
for app_name in pypi_ranking:
os.system('pip install {}'.format(app_name))
# PEP8違反状況の調査
for app_name in pypi_ranking:
_path_base = '~/.virtualenvs/test1/lib/python2.7/site-packages/{}/'
path = _path_base.format(app_name)
# flake8でのPEP8違反
try:
flake8_warning = get_flake8_warning(path)
# pyファイルの合計行数をカウント
lines = get_py_file_line_count(path)
per_line = float(flake8_warning) / float(lines)
print 'APP:{} TotalLine:{} PEP8-warning:{} ' \
'PEP8-warning-each-line:{}'.\
format(app_name, lines, flake8_warning, per_line)
except Exception:
print "ERROR directory does not exist:{}".format(app_name)
>>> python check.py
APP:simplejson TotalLine:4041 PEP8-warning:176 PEP8-warning-each-line:0.0435535758476
APP:setuptools TotalLine:9004 PEP8-warning:496 PEP8-warning-each-line:0.0550866281653
APP:requests TotalLine:17168 PEP8-warning:3218 PEP8-warning-each-line:0.187441752097
ERROR directory does not exist:distribute
APP:Jinja2 TotalLine:10806 PEP8-warning:93 PEP8-warning-each-line:0.00860632981677
APP:lxml TotalLine:6533 PEP8-warning:354 PEP8-warning-each-line:0.0541864380836
APP:docutils TotalLine:39915 PEP8-warning:6685 PEP8-warning-each-line:0.167480896906
APP:MarkupSafe TotalLine:816 PEP8-warning:8 PEP8-warning-each-line:0.00980392156863
....
エディタ毎にPEP8チェックプラグインの導入
- PyCharm : 標準で搭載しています。
- vim : vimでpythonのコーディングスタイルを自動でチェック&自動修正する
- Emacs : Emacs で Python のソースコードを編集するあいだ常に PEP8 のチェックをおこなう
- Ecrips : Eclipse (luna)とPydevでPythonの開発環境を作る #PEP8に準拠
さいごに
ブーメラン怖いので自分が公開しているモジュールのPEP8違反状況を調べてみた。適切にPEP8チェックプラグインを導入して意識してコードを書いていけば、そうそうPEP8違反をすることは無いと思います。
参考
PEP 0008 -- Style Guide for Python Code
PEP 20 -- The Zen of Python
プログラマが持つべき心構え (The Zen of Python)
PyPI Ranking