Open13

PythonのVSCodeとDevContainerの環境設定

shimakaze_softshimakaze_soft

PyrightをVSCodeに設定

Microsoft製のPython向け静的解析ツール。

プロジェクトのルートディレクトリ上から、.vscode/extensions.jsonを作成し、"ms-pyright.pyright" を入れることで、必ずpyrightの拡張機能が入っているかVSCodeを起動する度に聞いてきてくれるようになる。

.vscode/extensions.json
{
  "recommendations": [
    "ms-pyright.pyright"
  ]
}

プロジェクトのルートディレクトリ上に pyrightconfig.jsonを作成する。

{
    "pythonVersion": "3.4",
    "venvPath": "/Users/shimakaze_soft/.venvs",
    "venv": "dev_374",

    "include": [
        "app",
        "db"
    ],
    "ignore": [
        "db/migrations/versions"
    ],
}
  • pythonVersion : Python 3.4でサポートされていない文法がProblemとして検出される
  • venvPath : 自分のvenvが保存されてるパス
  • venv : venvPathの中でも自分が対象としたいvenvを指定
  • include : pyrintの対象としたいディレクトリ
  • ignore : includeで対象としたとしても、そのなかでpyrintを除外したいパス

後はVSCodeを再起動すれば設定が読み込まれる。

shimakaze_softshimakaze_soft

LinterとFormatterや整形ツールなどについて

https://qiita.com/sin9270/items/85e2dab4c0144c79987d

Linter

コードに問題点がないかを確認する静的解析ツール。

Pythonの場合、bool値の比較は==ではなくisで比較する、PEP8に従った書き方になっているかをチェックなどを行う。

linterの種類

  • flake8 : pycodestyle、pyflakes、mccabeの3つのlinterをまとめたもの
  • pylint : VSCodeのデフォルトのlinter。
  • Prospector : さらに多くのlinterをまとめたラッパーであり、isort、pylintも入っている。

formatter

formatterは、コードのスタイルをチェックするツール。
linterとは違って、スペースの数や挿入位置、改行の位置など、プログラムの動作ではなく見た目に関わる内容を自動修正する。

  • autopep8 : PEP8に準拠するようにコードを整形するツール
    • pycodestyleの検出したエラーを修正してくれたり、全てのエラーに対応しているわけではないことに注意
    • Pythonのformatterの中では古株だが、最近は人気が落ちている
  • yapf : Googleが開発しているコードフォーマッターであり、カスタマイズ性が高く、多くの項目を設定できる
  • black : 他のフォーマッターよりも制限が厳しく、設定できるオプションがかなり少ないが、細かいスタイルまで統一してくれる

その他の整形ツール

  • mypy : 型チェックを行うツール
  • pyright : Microsoft製の型チェックを行うツール
  • isort : import文の並び順をチェックと自動整形するツール
    • PEP8で規定されている標準ライブラリ > サードパーティライブラリ > ローカルライブラリの順に加えて、アルファベット順にソートする
  • pep8-naming : 変数や関数の命名ルールがPEP8に従っているかチェックするツール
  • Bandit : セキュリティ的に問題がありそうな箇所を判定してくれるツール

VSCode にflake8とautopep8を導入する

Python の拡張( Python : ms-python.python) を入れる

.vscode/extensions.json
{
  "recommendations": [
    "ms-python.python"
  ]
}

ms-python.pythonを導入すれば、flake8とautopep8も自動的に入っている。

VSCodeの作業用設定ファイルを編集する

.vscode/settings.jsonを作成して編集する。

{
  "python.pythonPath": "/usr/local/bin/python",  // pythonの実行環境
  "python.analysis.extraPaths": [
    "/usr/local/lib/python3.10/site-packages/"
  ],
  "python.analysis.completeFunctionParens": true,
  "python.analysis.typeCheckingMode": "strict",
  "python.analysis.diagnosticMode": "workspace",

  // 言語サーバーはPylanceを使用
  "python.languageServer": "Pylance",

  // Linter(flake8) settings
  "python.linting.enabled": true,  // 文法チェックを行う
  "python.linting.pylintEnabled": false,  // pylint は使わない
  "python.linting.pycodestyleEnabled": false, // pycodestyleは使わない
  "python.linting.flake8Enabled": true,  // 文法チェックにはflake8を使用する
  "python.linting.flake8Args": [  // flake8 の設定
    "--ignore=E111, E114, E402, E501"
  ],

  // Formatter(autopep8) settings
  "python.formatting.provider": "autopep8",  // 自動整形に autopep8 を使う
  "python.formatting.autopep8Args": [  // autopep8 の設定
    "--indent-size=4",
    "--max-line-length",
    "160",
    "--ignore=E111, E114, E402, E501"
  ],

  "[python]": {
    "editor.tabSize": 4,  // インデントレベルは4
    "editor.formatOnSave": true,  // 保存時に自動整形を行う
    "editor.formatOnPaste": false,  // ペースト時に自動整形を行わない
    "editor.formatOnType": false,  // 入力後に自動整形を行わない
  },
}
  • python.analysis.completeFunctionParens : functionの入力補完。デフォルトはfalse。
shimakaze_softshimakaze_soft

flake8の設定

.vscode/settings.json
{
  // Linter(flake8) settings
  "python.linting.enabled": true,  // 文法チェックを行う
  "python.linting.pylintEnabled": false,  // pylint は使わない
  "python.linting.pycodestyleEnabled": false, // pycodestyleは使わない
  "python.linting.flake8Enabled": true,  // 文法チェックにはflake8を使用する
  "python.linting.flake8Args": [  // flake8 の設定
    "--ignore=E111, E114, E402, E501"
  ]
}
  • python.linting.pylintEnabledはデフォルトはtrueであるため、false に設定する
  • python.linting.flake8Enabled だけが 有効 になり、文法チェックツールに flake8 が設定される。

文法チェックのルール

.vscode/settings.json
{
  // Linter(flake8) settings
  "python.linting.flake8Args": [  // flake8 の設定
    "--ignore=E111, E114, E402, E501"
  ]
}
  • E111 : indentation is not a multiple of four をチェックする
  • E114 : indentation is not a multiple of four (comment) をチェックする
  • E402 : module level import not at top of file をチェックする
  • E501 : line too long をチェックする

エラーコードについて

https://pep8.readthedocs.io/en/latest/intro.html#error-codes

shimakaze_softshimakaze_soft

autopep8の設定

.vscode/settings.json
{
  // Formatter(autopep8)
  "python.formatting.provider": "autopep8",
  "python.formatting.autopep8Args": [
    "--indent-size=4",
    "--max-line-length",
    "160",
    "--ignore=E111, E114, E402, E501"
  ]
}

autopep8 を使う設定

  • python.formatting.provider で自動整形ツールを設定。選択肢は以下の中から自動整形ツールを指定する。
    • autopep8
    • black
    • yapf

autopep8 で自動整形する内容を設定する

--indent-size=4 を設定することで自動整形の際にインデントを 2 で整形する
--ignore=E402 で import 文をファイルの先頭に移動する自動整形を抑止する

shimakaze_softshimakaze_soft

isorの設定

isortはデフォルトでVS Codeの標準のimport並び替え用のパッケージとして組み込まれているため、拡張機能として入れる必要はない。

ただし、VSCodeで設定は必要になる。

保存時にisortが自動で実行する設定

.vscode/settings.jsonに以下の設定を追加で記述する。

.vscode/settings.json
{
  "editor.codeActionsOnSave": {
    "source.organizeImports": true
  }
}

手動実行の場合

手動実行でisortを行う場合は、モジュールをインストールする必要がある。

$ pip install isort

blackを使用している場合は、isortのデフォルトのルールといくつか競合する場合がある。

black公式が対応箇所を以下でまとめています。

https://github.com/psf/black/blob/6d0bdc2f38d57ddf07e7d127215d51f8553997f9/docs/compatible_configs.md#isort

isortの設定は以下に記述することができます。

  • .isort.cfg
  • pyproject.toml
  • setup.cfg
  • tox.ini
  • .editorconfig

isortの実行方法は以下になる。

# ファイル単体
$ isort target_file.py

# ディレクトリ配下全て
$ isort -rc target_dir

.editorconfigに以下のisortの記述する。

.editorconfig
[*.py]
multi_line_output = 3
include_trailing_comma = True
force_grid_wrap = 0
use_parentheses = True
ensure_newline_before_comments = True
line_length = 88

indent_size = 4
  • line_length:1行の文字数
  • multi_line_output:複数行になる場合の変換方法

0 ~ 11の設定方法がある。
https://pycqa.github.io/isort/docs/configuration/multi_line_output_modes.html

  • include_trailing_comma:末尾にカンマを含めるか?になる。
  • ensure_newline_before_comments:コメント前の改行を許可
  • use_parentheses:改行する場合にバックスラッシュではなく、カッコを使用する。
shimakaze_softshimakaze_soft

Pythonに最適なVSCodeの拡張機能

上記以外にもVSCodeに最適な拡張機能はいくつかある。その中でもオススメを紹介。

TabNine

予測変換の一番上に、機械学習を使用した適切な補完候補が表示される

https://marketplace.visualstudio.com/items?itemName=TabNine.tabnine-vscode

.vscode/extensions.json
{
  "recommendations": [
    "TabNine.tabnine-vscode"
  ]
}

IntelliCode

IntelliCodeは、VSCode の Python、TypeScript/JavaScript、および Java 開発者向けのAI 支援開発機能を提供する。

https://marketplace.visualstudio.com/items?itemName=VisualStudioExptTeam.vscodeintellicode

.vscode/extensions.json
{
  "recommendations": [
    "visualstudioexptteam.vscodeintellicode"
  ]
}

Python Indent

  • Pythonインデントの精度が格段に上がる
  • 引数をカンマ区切りで入力する際などに、自動で綺麗にインデントを付けてくれる

https://marketplace.visualstudio.com/items?itemName=KevinRose.vsc-python-indent

.vscode/extensions.json
{
  "recommendations": [
    "KevinRose.vsc-python-indent"
  ]
}

Python Test Explorer for Visual Studio Code

VSCodeのサイドバーにTest用UIが追加される。
Test用UIから、実行したいテストの実行ボタンを押すだけでテストが実行できる。

テスト実行のほか、DEBUGモードでBreakPointを作りながら、変数の中身などを確認できる。

https://marketplace.visualstudio.com/items?itemName=LittleFoxTeam.vscode-python-test-adapter

.vscode/extensions.json
{
  "recommendations": [
    "LittleFoxTeam.vscode-python-test-adapter"
  ]
}

Python Preview

変数や配列の中身などを、視覚的に簡単に確認できるようになる。

別ウィンドウでかなり詳細に確認できるので、バグの原因も簡単に突き止められるようになり、デバッグの精度が非常に上がります。

https://marketplace.visualstudio.com/items?itemName=dongli.python-preview

.vscode/extensions.json
{
  "recommendations": [
    "dongli.python-preview"
  ]
}

その他はこちら

https://yurupro.cloud/767/#toc22

shimakaze_softshimakaze_soft

Pylanceの設定項目

https://qiita.com/icoxfog417/items/c17eb042f4735b7924a3

ms-python.pythonを入れれば自動でPylanceは導入される

https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance#settings-and-customization

python.analysis.typeCheckingMode

実行される型チェックの分析レベルを指定。

  • off:デフォルト値。型チェックは行われない。未解決のインポート/変数診断が作成されます。
  • basic:型チェックに関連しないルール(off時のチェックルール)と基本的な型チェックを行う。
  • strict:エラーに関する最も厳重な型チェックを実施。off時のチェックルールとbasic時のチェックルールも行う。

python.analysis.diagnosticMode

コードを分析して問題を報告する言語サーバーに、どのファイルを指定できるか設定するために使用される。

  • openFilesOnly (デフォルト値)
  • workspace

python.analysis.stubPaths

ユーザーがカスタムタイプのスタブを含むディレクトリへのパスを指定できるか設定するために使用される。各パッケージの型スタブファイルは、独自のサブディレクトリにあることが望ましい。

  • Default : ./typings

python.analysis.autoSearchPaths

事前定義された名前(srcなど)に基づいて検索パスを自動的に追加するために使用される。

  • true(Default)
  • false

python.analysis.extraPaths

インポート解決のための追加の検索パスを指定するために使用される。これにより、古い python.autoComplete.extraPaths 設定は置き換えられる。

  • デフォルト値:空の配列

python.analysis.diagnosticSeverityOverrides

ユーザーが必要に応じて、個々の診断の重大度レベルを上書きするために使用される。

  • error(赤い波線)
  • warning(黄色の波線)
  • information(青い波線)
  • none(ルールを無効にします)

キーとして使用できるルールは以下を参照。

https://github.com/microsoft/pylance-release/blob/main/DIAGNOSTIC_SEVERITY_RULES.md

.vscode/settings.json
{
    "python.analysis.diagnosticSeverityOverrides:" { 
        "reportUnboundVariable" : "information", 
        "reportImplicitStringConcatenation" : "warning" 
    }
} 

python.analysis.useLibraryCodeForTypes

タイプスタブが見つからない場合、パッケージのソースコードを解析するために使用される。

  • true (Default)
  • false
shimakaze_softshimakaze_soft

Remote Containerを導入

https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers

.vscode/extensions.json
{
  "recommendations": [
    "ms-vscode-remote.remote-containers",
  ]
}

.devcontainer/devcontainer.jsonを作成

プロジェクトのルートディレクトリ上で.devcontainer/devcontainer.jsonを作成する。

.devcontainer/devcontainer.json
{
  "name": "project?name",
  "dockerFile": "Dockerfile",
  "runArgs": [
    // Sync git config
    "-v",
    "${env:HOME}${env:USERPROFILE}/.gitconfig:/root/.gitconfig"
  ],
  "settings": {
    "python.pythonPath": "/usr/local/bin/python",
    "python.analysis.extraPaths": [
      "/usr/local/lib/python3.10/site-packages/"
    ]
  },
  "postCreateCommand": "pip install -r requirements.txt",
  "extensions": [
    "editorconfig.editorconfig",
    "ms-python.python"
  ]
}

Dockerfileの導入

Dockerfile
FROM python:3.10-slim

RUN apt-get update \
    && apt-get install -y --no-install-recommends --allow-unauthenticated \
    apt-utils \
    dialog \
    procps \
    git \
    lsb-release \
    gcc \
    build-essential \
    libmariadb-dev \
    && pip install --upgrade pip \
    && pip install --no-cache-dir \
    autopep8 flake8 isort \
    && apt-get autoremove -y \
    && apt-get clean -y \
    && rm -rf /var/lib/apt/lists/*

shimakaze_softshimakaze_soft

GitHub ActionsのCIでLinterとFormatterを動かす

.github/workflows/code_formatter.yml
name: Code Format Sample
on: [push]

jobs:
  build:
  runs-on: ubuntu-latest

  steps:
    - uses: actions/checkout@v3
    - name: Set up Python 3.10
      uses: actions/setup-python@v3
      with:
        python-version: 3.10

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install flake8 isort autopep8

    - name: Lint
      run: |
        flake8 target_file_or_directory
        isort --check --diff target_file_or_directory
        # black --check --line-length 119 target_file_or_directory
shimakaze_softshimakaze_soft

GitHubActionsで静的解析を自動で行う

PyrightをCI上で動作させて、commitしてきたソースコードが問題ないかチェックする仕組みを自動化することで、ソースの品質を一定上担保する

Pyright

一番上でも紹介したPyright。PyrightはPylanceのOSS版でもあり、同じくMicrosoft製。

プロジェクトのルートディレクトリ上にpyrightconfig.jsonを作成する。

pyrightconfig.json
{
  "pythonVersion": "3.10",
  "include": [
    "app",
  ],
  "exclude": [
    "**/.ipynb_checpoints",
    "**/__pycache__",
    "typings",
    "venv",
    ".venv"
  ],
  "reportUnusedImport": "information",
  "reportMissingImports": "information",
  "reportUnknownMemberType": "information",
  "reportOptionalCall": "information"
}

python.analysis.diagnosticSeverityOverridesのようなエラーにしないようにするルールの記述も可能です。

手動で動作させる

$ pip install pyright

https://github.com/simon-ritchie/apysc

pyrightで実行できます。pyrightconfig.jsonがあれば、それを自動で読み込みます。

$ pyright
Loading configuration file at /home/Users/shimakazesoft/app/pyrightconfig.json
Assuming Python platform Linux
stubPath /home/Users/shimakazesoft/app/typings is not a valid directory.
Searching for source files
Found 6 source files
pyright 1.1.267

....

1 error, 0 warnings, 3 informations 
Completed in 1.81sec

GitHubActionsに組み込む場合

- uses: actions/checkout@v3
- name: Run pyright
  uses: jakebailey/pyright-action@v1.4.1

lizard

サイクロマティック複雑度を計るツール。

循環的複雑度(サイクロマティック複雑度)とは、ソフトウェア測定法の一種。

プログラムの複雑度を測るのに使われる。
プログラムのソースコードから、線形的に独立した経路の数を直接数える。

https://debimate.jp/2021/05/19/【c-c-c-java対応】循環的複雑度の計測ツール-lizardの導入方/

以下で簡単にインストールできます。

$ pip install lizard

以下のコマンドで実行できます。
-lが言語を指定、-CがCCN(複雑度)のしきい値

# -C 10を指定した場合は10以上のものには警告を出す
$ lizard -l python -C 10 {file or directory}

出力結果の項目

  • CCN : 循環的複雑度。if文、for文、switch-case文などの条件分岐式が増えると数値が上がる。
  • NLOC : コメントを除いたメソッドやファイルのコード行数
  • token : トークンとはコンパイラが字句解析/構文解析する際の最小単位(要素)であり、ここでは関数中のトークン数
  • PARAM : メソッドのパラメータ数
  • length : コメントを含むメソッドやファイルのコード行数

複雑度の値(CCN)

出力結果に出てくるCCという値が複雑度を表す。

  • 1-10 : 安全なコードでテストしやすい
  • 11-20 : やや複雑なコード
  • 21-40 : 複雑なコードでテストが難しい
  • 41以上 : テスト不可能

GitHubActionsに組み込む

以下のようにシンプルに組み込む方法でも構わない

- name: lizard
  run: lizard -l python -C 10

以下のようにGitHub Marketplaceに公開さて、容易に導入可能でカスタマイズもしやすいやつもある。

https://github.com/marketplace/actions/lizard-runner

詳細はこちら

https://zenn.dev/u_not/articles/e9d0c47d306ba6

ちなみにデフォルト値はこうなっているらしい

  • CCN(循環的複雑度) : 15
  • length(コードの行数 : 1000
  • nloc(空白やコメントを引いたコード行数) : 1000000
  • parameter_count(引数の数) : 100
shimakaze_softshimakaze_soft

flake8の拡張機能

flake8には様々な拡張機能があり、以下のawesome-flake8-extensionsにまとまっています。

https://github.com/DmytroLitvinov/awesome-flake8-extensions

flake8-bugbear

flake8-bugbearでは.pyflakeやpycodestyleで提供されていないような,より詳細なコードのチェックが可能になります.flake8-bugbearの警告の一覧は,こちらを参照してください.

flake8-builtins

使用している変数や関数名が,組み込みオブジェクトの名前と被っていないかどうかをチェックします.

flake8-eradicate

コメントアウトされているコードを見つけて警告する拡張機能.

pep8-naming

変数や関数の命名がPEP8に準拠しているかどうかをチェックしてくれます.

flake8-expression-complexity

表現の複雑さを測定して警告を投げてくれる拡張機能です.expression complexityの正確な定義は分かりませんが,どうやらブーリアンの表現の複雑さを表しているようです.

flake8-cognitive-complexity

コードの認知的複雑度を計測し,警告を投げてくれる拡張機能です.認知的複雑度については,こちらの記事(Cognitive Complexity で、コードの読みやすさを定量的に計測しよう)が参考になります.

Bandit

pythonのコードにおけるセキュリティに関する問題をチェックしてくれる拡張機能。

$ pip install bandit
$ bandit -r app

https://tech.kusuwada.com/entry/2018/12/23/165526

pandas-vet

pandasを使ったコードのためのlinterです.

flake8-django

Djangoを使ったコードのためにlinterです.

flake8-pytest-style

pytestに関するコードスタイルをチェックしてくれる拡張機能です.

flake8-simplify

コードを簡素化するのに役立つ flake8 プラグイン。


dlint

ベストコーディングプラクティスを奨励し、Python コードが安全であることを保証するためのツール。

shimakaze_softshimakaze_soft

コードの静的解析に役立つツール

コードの複雑度や保守のしやすさなどを計る手法のことを、コードメトリクスと呼びますが、手法には様々あります。

上記のlizardはもちろんのこと、コードの保守性を高めるためには、複雑度などを計るためのツールを使用して、静的解析を行っていきます。

Radon

Pythonのメトリックスを計測するためのツール。
コードの複雑度や行数を取得したりできる。

https://github.com/rubik/radon

https://qiita.com/mima_ita/items/5010aaa6808b7290d68d

Maintainability Indexまで計れる

Microsoftが作り出した指標であり、保守容易性指数(Maintainability Idex)といいます。

100が最大値であり、100に近いほど保守がしやすいということを表します。
計算式等は以下で求めることができるそうです。

https://github.com/MicrosoftDocs/visualstudio-docs/blob/main/docs/code-quality/code-metrics-maintainability-index-range-and-meaning.md

Halstead複雑度

上記の保守容易性指数(MI)の計算に必要な複雑度の一つ。

詳しくはこちら

https://qiita.com/AngryMane/items/4d5d1238405e66374aa6#halstead複雑度のvolume

https://github.com/rubik/xenon