VS CodeによるPython開発環境のテンプレ

## 0. はじめに
sublime使いだった僕が（使い込んではいなかったけど）社内のPython開発環境を統一するためにVS Codeの色々を調べたので，そのまとめです．

以下ができるような開発環境の構築を目的としています．

- 複数人がローカルで開発する時に，環境を揃えたい．
- ローカルからリモートサーバーにアクセスして開発したい．
- プロジェクトごとに依存関係を整理したい．
- コーディングスタイルや型などのチェックを入れたい．

Pythonの環境周りはPipenvで管理し，ローカルでdockerを立ち上げてその中で開発するためのテンプレです．

## 1. install
[Setting up Visual Studio Code](https://code.visualstudio.com/docs/setup/setup-overview)

## 2. Extension
### 2.1. 必須
以下は必須．

- python
- Remote Development
- Remote SSH
- git lens

### 2.2. オプショナル
その他このへんが参考になる．

[VSCodeのオススメ拡張機能 24 選 (とTipsをいくつか) - Qiita](https://qiita.com/sensuikan1973/items/74cf5383c02dbcd82234)

[VSCodeの拡張機能 おすすめ(8/14更新) - Qiita](https://qiita.com/EbXpJ6bp/items/4b87a092a3d6a0ecf595)

(sublimeでいうところのgit gutter的なextensionを一生懸命探してたけど，ないなあと思っていたらデフォルトでそういう機能がついていた．すごい．）

## 3. プロジェクトのテンプレ
以下にコードを起きました．
[vscode_python_template](https://github.com/kazetof/vscode_python_template)

### 3.1. ディレクトリ構造
プロジェクトのディレクトリ構造は以下のようにすると良さげ．

```
.
├── Pipfile
├── Pipfile.lock
├── .devcontainer
├── .venv
├── .vscode
└── some_project
```

- `Pipfile`にpythonの依存関係を記述する．
- `.devcontainer`に立ち上げるdockerの情報を記述する．
- `.venv`にプロジェクトごとのPythonの仮想環境が置かれる．
- `.vscode`にVS Codeの設定ファイルが置かれる．

vs codeでvenvを使うときに，

- venvをまとめて置いているディレクトリへパスを通す
- 各プロジェクト以下にvenvを置く

の二つのやり方があったが，後者を選んだ．
（現在読み込んでいる仮想環境が，想定していたものと異なる仮想環境を読み込んでいるミスがよくあるので）


### 3.2. `Pipfile`

```Pipfile
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]
ipython = "==7.3.0"
mypy = "==0.720"
autopep8 = "==1.4.4"
pep8 = "==1.7.1"
flake8 = "==3.7.8"
pylint = "==2.3.1"

[packages]
numpy = "==1.17"
pandas = "==0.25.0"

[requires]
python_version = "3.7.2"
```

以下の環境変数を指定してプロジェクトディレクトリに仮想環境を配置する．
`-d`はdev-packagesをインストールするオプション．

```shell

$ PIPENV_VENV_IN_PROJECT=true pipenv install -d
```

2019/8/5 追加
ちなみに，VS Codeのterminalは自動的に仮想環境上で起動するので，VS Code内で立ち上がっているTerminal上で`pipenv install`する時は以下のように現在起動している仮想環境を引き継がないように環境変数を設定した方が良い．
（そうしないと，例えばpythonのバージョンを3.6.8 -> 3.7.2に変えたりしても，元のpythonのバージョンの3.6.8を引き継いで変更が反映されないと思う．）

```shell
$ PIPENV_IGNORE_VIRTUALENVS=1 PIPENV_VENV_IN_PROJECT=true pipenv install -d
```

### 3.3. `.devcontaier`

```
.
├── Pipfile
├── Pipfile.lock
├── .devcontainer
  ├── Dockerfile
  └── devcontainer.json
```

#### 3.3.1. `devcontainer.json`
vs codeの裏側でdockerを起動するためconfig．

```devcontainer.json
{
	"name": "Python3_Pipenv",
	"dockerFile": "Dockerfile",
	"appPort": 9000,
	"context": "..",
	"extensions": [
		"ms-python.python"
	],
	"settings": {
		"python.pythonPath": "/usr/local/bin/python"
	}
}
```

#### 3.3.2. `Dockerfile`

dockerではgitなどshellでよく使用するものと，pipenv環境だけインストールするようにした．
その他のpython関連はpipenvで管理する．

```Dockerfile
FROM ubuntu:18.04

ENV HOME_DIR /root

# Environment Setting
RUN apt update
RUN apt install -y python3 python3-pip build-essential libssl-dev libffi-dev python-dev git

# for jupyter notebook
RUN apt install -y libsqlite3-dev libreadline6-dev libbz2-dev libssl-dev libsqlite3-dev libncursesw5-dev libffi-dev libdb-dev libexpat1-dev zlib1g-dev liblzma-dev libgdbm-dev libmpdec-dev

# Install any missing dependencies for enhanced language service
RUN apt-get install -y libicu[0-9][0-9]

# install pyenv
RUN git clone git://github.com/pyenv/pyenv.git $HOME_DIR/.pyenv
RUN apt install -y zlib1g-dev wget

ENV PYENV_ROOT="${HOME_DIR}/.pyenv"
ENV PATH="${PATH}:${PYENV_ROOT}/bin"

RUN eval "$(pyenv init -)"

RUN pyenv install 3.7.2
# RUN pyenv install 3.6.8

# install pipenv
RUN pip3 install pipenv
ENV LC_ALL=C.UTF-8 LANG=C.UTF-8

RUN mkdir /workspaces
WORKDIR /workspaces

# Clean up
RUN apt-get autoremove -y \
    && apt-get clean -y \
    && rm -rf /var/lib/apt/lists/*

# Set the default shell to bash rather than sh
ENV SHELL /bin/bash
```

### 3.4. `.vscode`

```
.
├── Pipfile
├── Pipfile.lock
└── .vscode
    └── setting.json
```

#### 3.4.1. `setting.json`
vscodeの設定．pythonのlinting関連をとりあえず色々ONにしている．

- 2019/8/5 Pythonコードの時にインデントをspace 4つにするconfigを追加した．

```settings.json
{
    "files.exclude": {
        "**/*.pyc": true,
        ".nyc_output": true,
        "obj": true,
        "bin": true,
        "**/__pycache__": true,
        "**/.mypy_cache/**": true,
    },
    "[python]": {
        "editor.insertSpaces": true,
        "editor.detectIndentation": true,
        "editor.tabSize": 4
    },
    "python.pythonPath": "${workspaceRoot}/.venv/bin/python",
    "python.venvPath": ".venv",
    "python.pipenvPath": "/usr/local/bin/pipenv",
    "python.linting.pylintEnabled": true,
    "python.linting.mypyEnabled": true,
    "python.linting.flake8Enabled": true,
    "python.linting.pep8Enabled": true,
    "python.linting.pep8Args": ["--ignore=E501"],
    "python.linting.flake8Args": [
        "--max-line-length=120"
    ]
}
```

## 4. その他
### 4.1. リモートサーバーへのアクセス
`Remote-SSH`を使えばいけた．
この辺を参照．

[Developing on Remote Machines using SSH and Visual Studio Code](https://code.visualstudio.com/docs/remote/ssh#_getting-started)

## 4.2. コマンドでvs codeの起動
あると便利．

[ターミナルからVisual Studio Codeを起動する方法【公式の方法】 - Qiita](https://qiita.com/naru0504/items/c2ed8869ffbf7682cf5c)