PythonのVSCodeとDevContainerの環境設定

PyrightをVSCodeに設定
Microsoft製のPython向け静的解析ツール。
プロジェクトのルートディレクトリ上から、.vscode/extensions.json
を作成し、"ms-pyright.pyright"
を入れることで、必ずpyrightの拡張機能が入っているかVSCodeを起動する度に聞いてきてくれるようになる。
{
"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を再起動すれば設定が読み込まれる。

LinterとFormatterや整形ツールなどについて
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
) を入れる
{
"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。

flake8の設定
{
// 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 が設定される。
文法チェックのルール
{
// 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 をチェックする
エラーコードについて

autopep8の設定
{
// 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 文をファイルの先頭に移動する自動整形を抑止する

isorの設定
isortはデフォルトでVS Codeの標準のimport並び替え用のパッケージとして組み込まれているため、拡張機能として入れる必要はない。
ただし、VSCodeで設定は必要になる。
保存時にisortが自動で実行する設定
.vscode/settings.json
に以下の設定を追加で記述する。
{
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
}
手動実行の場合
手動実行でisortを行う場合は、モジュールをインストールする必要がある。
$ pip install isort
blackを使用している場合は、isortのデフォルトのルールといくつか競合する場合がある。
black公式が対応箇所を以下でまとめています。
isortの設定は以下に記述することができます。
- .isort.cfg
- pyproject.toml
- setup.cfg
- tox.ini
- .editorconfig
isort
の実行方法は以下になる。
# ファイル単体
$ isort target_file.py
# ディレクトリ配下全て
$ isort -rc target_dir
.editorconfig
に以下のisort
の記述する。
[*.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の設定方法がある。
- include_trailing_comma:末尾にカンマを含めるか?になる。
- ensure_newline_before_comments:コメント前の改行を許可
- use_parentheses:改行する場合にバックスラッシュではなく、カッコを使用する。

Pythonに最適なVSCodeの拡張機能
上記以外にもVSCodeに最適な拡張機能はいくつかある。その中でもオススメを紹介。
TabNine
予測変換の一番上に、機械学習を使用した適切な補完候補が表示される
{
"recommendations": [
"TabNine.tabnine-vscode"
]
}
IntelliCode
IntelliCodeは、VSCode の Python、TypeScript/JavaScript、および Java 開発者向けのAI 支援開発機能を提供する。
{
"recommendations": [
"visualstudioexptteam.vscodeintellicode"
]
}
Python Indent
- Pythonインデントの精度が格段に上がる
- 引数をカンマ区切りで入力する際などに、自動で綺麗にインデントを付けてくれる
{
"recommendations": [
"KevinRose.vsc-python-indent"
]
}
Python Test Explorer for Visual Studio Code
VSCodeのサイドバーにTest用UIが追加される。
Test用UIから、実行したいテストの実行ボタンを押すだけでテストが実行できる。
テスト実行のほか、DEBUGモードでBreakPointを作りながら、変数の中身などを確認できる。
{
"recommendations": [
"LittleFoxTeam.vscode-python-test-adapter"
]
}
Python Preview
変数や配列の中身などを、視覚的に簡単に確認できるようになる。
別ウィンドウでかなり詳細に確認できるので、バグの原因も簡単に突き止められるようになり、デバッグの精度が非常に上がります。
{
"recommendations": [
"dongli.python-preview"
]
}
その他はこちら

Pylanceの設定項目
ms-python.python
を入れれば自動でPylanceは導入される
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(ルールを無効にします)
キーとして使用できるルールは以下を参照。
{
"python.analysis.diagnosticSeverityOverrides:" {
"reportUnboundVariable" : "information",
"reportImplicitStringConcatenation" : "warning"
}
}
python.analysis.useLibraryCodeForTypes
タイプスタブが見つからない場合、パッケージのソースコードを解析するために使用される。
- true (Default)
- false

Remote Containerを導入
{
"recommendations": [
"ms-vscode-remote.remote-containers",
]
}
.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の導入
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/*

GitHub ActionsのCIでLinterとFormatterを動かす
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

GitHubActionsで静的解析を自動で行う
PyrightをCI上で動作させて、commitしてきたソースコードが問題ないかチェックする仕組みを自動化することで、ソースの品質を一定上担保する
Pyright
一番上でも紹介したPyright。PyrightはPylanceのOSS版でもあり、同じくMicrosoft製。
プロジェクトのルートディレクトリ上に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
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
サイクロマティック複雑度を計るツール。
循環的複雑度(サイクロマティック複雑度)
とは、ソフトウェア測定法の一種。
プログラムの複雑度を測るのに使われる。
プログラムのソースコードから、線形的に独立した経路の数を直接数える。
以下で簡単にインストールできます。
$ 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に公開さて、容易に導入可能でカスタマイズもしやすいやつもある。
詳細はこちら
ちなみにデフォルト値はこうなっているらしい
- CCN(循環的複雑度) : 15
- length(コードの行数 : 1000
- nloc(空白やコメントを引いたコード行数) : 1000000
- parameter_count(引数の数) : 100

flake8の拡張機能
flake8には様々な拡張機能があり、以下の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
pandas-vet
pandasを使ったコードのためのlinterです.
flake8-django
Djangoを使ったコードのためにlinterです.
flake8-pytest-style
pytestに関するコードスタイルをチェックしてくれる拡張機能です.
flake8-simplify
コードを簡素化するのに役立つ flake8 プラグイン。
dlint
ベストコーディングプラクティスを奨励し、Python コードが安全であることを保証するためのツール。

コードの静的解析に役立つツール
コードの複雑度や保守のしやすさなどを計る手法のことを、コードメトリクスと呼びますが、手法には様々あります。
上記のlizardはもちろんのこと、コードの保守性を高めるためには、複雑度などを計るためのツールを使用して、静的解析を行っていきます。
Radon
Pythonのメトリックスを計測するためのツール。
コードの複雑度や行数を取得したりできる。
Maintainability Indexまで計れる
Microsoftが作り出した指標であり、保守容易性指数(Maintainability Idex)といいます。
100が最大値であり、100に近いほど保守がしやすいということを表します。
計算式等は以下で求めることができるそうです。
Halstead複雑度
上記の保守容易性指数(MI)の計算に必要な複雑度の一つ。
詳しくはこちら

FastAPIに適したRemoteContainer