11
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

NSSOLAdvent Calendar 2019

Day 15

Python パッケージを作成する際の確認事項

Last updated at Posted at 2019-12-15

初めに

Python パッケージを作成する際,個人的に気を付けていることをまとめます.

以下,Python 3.5 以降の使用を前提とします.

確認事項

フォーマットを統一する

開発者によって文字コードや改行コードが異なると厄介なので,EditorConfig を利用して統一しましょう.

.editorconfig
root = true

[*]
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true

[*.py]
indent_style = space
indent_size = 4

依存パッケージのバージョンを明記する

他の開発者が実行環境を再現できるように,setup.pyrequirements.txt に依存パッケージのバージョンを明記しましょう.

setup.cfg
[options]
install_requires = numpy>=1.11.0, scipy>=0.17.0

pipenv を使うと尚良いです.

コーディング規約に準拠する

複数人が一貫したコードを記述できるように,コーディング規約に準拠しましょう.

PEP 8 -- Style Guide for Python Code | Python.org

Flake8Pylint を利用して違反しているかどうかを確認します.無視したい警告がある場合,setup.cfg.flake8 にその旨を記述して下さい.

setup.cfg
[flake8]
ignore = E221, E241, E251, E402
max-line-length = 79

autopep8black を使うと,コードを自動で整形してくれます.

エンコーディング宣言を記述しない

UTF-8 でコードを記述する場合,次のエンコーディング宣言は推奨されないため,削除しましょう.

# coding: utf-8

ファイルの先頭でインポートする

特に理由がなければ,ファイルの先頭でインポートしましょう.ただし,依存パッケージを制限したい場合,関数の内部でインポートすることがあります.以下をご参照下さい.

命名規約を遵守する

次のように命名しましょう.

種類
パッケージ my_favorite_package
モジュール my_favorite_module
クラス MyFavoriteClass
メソッド my_favorite_method
関数 my_favorite_function
変数 my_favorite_variable
定数 MY_FAVORITE_CONSTANT
組み込み関数を関数名(変数名)に充てない

Python は,60 以上の組み込み関数を備えています.

組み込み関数 — Python 3.8.0 ドキュメント

例えば,dict = {'a': 1.0} と書くと,組み込み関数 dict が上書きされてしまうので注意しましょう.

マジックナンバーを定数として保持する

マジックナンバーに適切な名前を付けて保持することで,意味が与えられ,後々の修正も容易になります.

品詞に配慮する

クラス名や変数名は名詞,メソッド名や関数名は動詞というように,品詞に配慮しましょう.

循環的複雑度を抑制する

循環的複雑度は,コードの複雑度を測る指標で,値が大きいほどバグを含む可能性が高いことを示唆します. setup.cfg.flake8 で設定することで,循環的複雑度を計測することができます.

setup.cfg
[flake8]
ignore = E221, E241, E251, E402
max-complexity = 10
max-line-length = 79

分岐を減らす,または,メソッド(関数)を適当な単位に分割して,循環的複雑度を 10 以下に抑制してください.10 以下が難しい場合,任意の値を定めて下さい.

入れ子を浅くする

入れ子を浅くすることで,可読性が高くなります.ただし,循環的複雑度は下がらないことに注意して下さい.

アクセサを実装しない

Python は,属性を隠蔽しないため,直接代入,参照が可能です.したがって, 純粋なアクセサの実装は,無意味です.

ログを出力する

PEP 282 -- A Logging System | Python.org

ログを出力する場合,print 関数ではなく,logging.Logger を利用しましょう.

処理したい例外を明示的に指定する

実行に失敗したとき,原因の特定が容易になります.

def div(a, b):
    try:
        ret = a / b
    except Exception as e:
        ret = np.nan

    return ret
def div(a, b):
    try:
        ret = a / b
    except ZeroDivisionError as e:
        ret = np.nan

    return ret

docstring を記述する

PEP 257 -- Docstring Conventions | Python.org

多くのパッケージは,次の記法を採用しています.

def div(a, b):
    """Division.

    Parameters
    ----------
    a
        Dividend.

    b
        Divisor.

    Returns
    -------
    ret
        Result.
    """

    try:
        ret = a / b
    except ZeroDivisionError as e:
        ret = np.nan

    return ret

PEP257 に準拠していることを pydocstyle で確認して下さい.

doctest を記述する

全てのパブリッククラスや関数に doctest を記述してください.

def div(a, b):
    """Division.

    Parameters
    ----------
    a
        Dividend.

    b
        Divisor.

    Returns
    -------
    ret
        Result.

    Examples
    --------
    >>> a = 8.0
    >>> b = 4.0
    >>> div(a, b)
    2.0
    """

    try:
        ret = a / b
    except ZeroDivisionError as e:
        ret = np.nan

    return ret

型ヒントを記述する

PEP 484 -- Type Hints | Python.org

型に関する注釈を付けることで,可読性が高くなります.

def div(a: float, b: float) -> float:
    """Division.

    Parameters
    ----------
    a
        Dividend.

    b
        Divisor.

    Returns
    -------
    ret
        Result.

    Examples
    --------
    >>> a = 8.0
    >>> b = 4.0
    >>> div(a, b)
    2.0
    """

    try:
        ret = a / b
    except ZeroDivisionError as e:
        ret = np.nan

    return ret

PEP484 に準拠していることを mypy で確認して下さい.

単体テストを実施する

開発途中であってもテストコードを必ず記述しましょう.

unittestpytestnose を適宜利用して下さい.特に,pytest を利用する場合,以下のような便利なプラグインがあります.

  • pytest-runner: setuptools で pytest を実行
  • pytest-cov: 単体テスト時に網羅率を計測
  • pytest-pydocstyle: 単体テスト時に pydocstyle を実行
  • pytest-flake8: 単体テスト時に flake8 を実行
  • pytest-mypy: 単体テスト時に mypy を実行

単体テストは,CircleCI などの CI サービス上で実行し,coveralls や codecov に網羅率を記録できると望ましいです.

ドキュメントを作成する

Sphinx を用いてドキュメントを作成して下さい.

終わりに

CONTRIBUTING.md に以上のことを明記して開発の秩序を保ちましょう.

参考文献

Python のコーディング規約 PEP8 に準拠する - Qiita
循環的複雑度を下げたい - Qiita
ネストの深さは闇の深さ - Qiita
Pythonでロギングを学ぼう - Qiita
Python の logging について - Qiita
pythonのloggingモジュールでログ出力をする時に付加的な情報を出力する方法 - Qiita
Codecovを使ってカバレッジを計測する - Qiita
PythonプロジェクトのドキュメントをSphinxで作成する - Qiita

11
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?