VSCodeでPython・Django + JupyterLabでPython (Windows)

# はじめに
- つまみ食いしていたら、環境が混沌としてきたので、シンプルなものを再構築しました。
- DockerやWSL2、あるいは、Anacondaのようなものは使用せず、素のPythonを使います。

#### 環境
- Windows 10 Pro 20H2
- Python 3.8.8
- Visual Studio Code 1.54.2

# VS Code で Python
- 公式ドキュメント通りにPythonとVSCodeを導入します。
    - [Visual Studio Code を使用して Python 初心者向けの開発環境をセットアップする](https://docs.microsoft.com/ja-jp/learn/modules/python-install-vscode/) (Microsoft)
        - とても分かり易くかかれています。
        - LinuxやOSX向けの情報もあります。
- 大まかな流れ
    - Python
        - [Python のダウンロード ページ](https://www.python.org/downloads/)からPython 8 インストーラをダウンロードします。
            - インストーラを含まないZIPもあるので注意しましょう。
        - インストールします。
            - パスを通す設定はしましょう。
            - 他はデフォルト設定で問題ありません。
            - インストール後、パスが通っていれば、`py --version`でバージョンが表示できます。
    - VS Code
        - [Visual Studio Code のダウンロード ページ](https://code.visualstudio.com/Download)から、インストーラをダウンロードします。
        - インストールします。
        - MS純正のPython拡張機能を導入します。
        - デフォルトインタプリタを設定します。

# VS Code で Django
プロジェクトを置くベースフォルダを仮に`D:\development\python`とします。

### pip の更新とモジュールの確認

```text
D:\development\python\>python -m pip install --upgrade pip
~ 略 ~

D:\development\python\>pip list
Package    Version
---------- -------
pip        21.0.1
setuptools 52.0.0
```

### virtualenv の導入
virtualenv とともに依存モジュールが導入されます。

```text
D:\development\python\>pip install virtualenv
~ 略 ~

D:\development\python\django>pip list
Package    Version
---------- -------
appdirs    1.4.4
distlib    0.3.1
filelock   3.0.12
pip        21.0.1
setuptools 49.2.1
six        1.15.0
virtualenv 20.4.2
```

### django 用仮想環境の構築、アクティベート
`django`フォルダに仮想環境を作り、アクティベートして、カレントディレクトリを移動します。

```text
D:\development\python\>virtualenv django
~ 略 ~

D:\development\python>django\scripts\activate

(django) D:\development\python>cd django
```

### 更新の必要なパッケージを確認して更新
```text
(django) D:\development\python\django>pip list -o
Package    Version Latest Type
---------- ------- ------ -----
setuptools 49.2.1  54.2.0 wheel

(django) D:\development\python\django>pip install -U setuptools
~ 略 ~
Successfully installed setuptools-54.2.0
```


### django 導入、プロジェクト作成
django を導入した上で、`django`フォルダ内に`practice`プロジェクトを作ります。

```text
(django) D:\development\python\django>pip install django
~ 略 ~

(django) D:\development\python\django>django-admin startproject practice .

(django) D:\development\python\django>dir /b
.gitignore
Lib
manage.py
practice
pyvenv.cfg
Scripts
```

### VS Code 接続
接続するフォルダからVS Codeを起動します。

```text
(django) D:\development\python\django>cd practice

(django) D:\development\python\django\practice>code .
```

`Ctrl+Shift+P`を押して、「Pythonインタプリタを選択」します。
環境の相違で同じ名前が二つありますが、パスからして青いフォーカスのあたっている方ですね。
![スクリーンショット 2021-03-02 230758.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365845/692d5ab5-715c-01a6-b97f-060474c7e5f4.jpeg)
選択すると、左下に選択結果が表示されます。
![スクリーンショット 2021-03-02 231323.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365845/b5e7de8c-fb49-8d73-8a47-56602c9c3aa9.jpeg)
左端のメニューで「実行」を選び、「launch.json ファイルを作成」をクリックします。
![スクリーンショット 2021-03-02 231733.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365845/5e4ab2b6-27a6-7dbe-1d93-78b268111442.jpeg)
`python`を選んで、
![スクリーンショット 2021-03-02 232521.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365845/9215762f-d51f-345b-cd32-e87df16b37d1.jpeg)
次に`django`を選びます。
![スクリーンショット 2021-03-02 232657.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365845/15ffd152-870d-b4d7-0abe-4ef6e7ef3d45.jpeg)
開いた`launch.json`をそっと閉じて、左上の実行ボタンを押すとサーバが起動します。
(ターミナルから起動する場合は、`python manage.py runserver`です。)
![スクリーンショット 2021-03-02 232846.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365845/1db4831a-29f4-49de-fdfd-3c243e9e8a2f.jpeg)
下部のターミナルに、以下のような感じで表示されます。

```text
System check identified no issues (0 silenced).
You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
March 02, 2021 - 23:28:58
Django version 3.1.7, using settings 'practice.settings'
Starting development server at http://127.0.0.1:8000/   
Quit the server with CTRL-BREAK.
█
```
- マイグレーションについて警告されていますが、[チュートリアル中に「取り敢えず無視」と書かれている](https://docs.djangoproject.com/ja/3.0/intro/tutorial01/#the-development-server)ので放置します。

書かれているとおり、`http://localhost:8000/`へアクセスしてロケットが飛べば成功です。
![スクリーンショット 2021-03-02 233126.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365845/fbe29a95-0f92-f482-16ba-8f9b198ee4b4.jpeg)

### 普段使いのショートカット
#### VS Code の設定
素のVS Codeを起動(プロジェクトからではなく)して、「設定 (Ctel+,)」を開き、「設定の検索」で`python venv`を探すと、

```text
Python: Venv Path
Path to folder with a list of Virtual Environments (e.g. ~/.pyenv, ~/Envs, ~/.virtualenvs).
```

のような感じの項目が見つかるので、使い方に合わせて、

```text
~, ~/.., ~/.env, ~/.venv, ~/venv, ~/../.env, ~/../.venv, ~/../venv
```

などと、設定しておきます。
こうすることで、VS Codeが仮想環境を見つけやすくなります。
(`setings.json`を直接編集するなら、`"python.venvPath": "~, ~/.., ~/.env, ~/.venv, ~/venv, ~/../.env, ~/../.venv, ~/../venv",`などと追加します。)


なお、VS Codeのターミナルが仮想環境を認識していない場合は、いったんターミナルを破棄(ゴミ箱)して、再度開けば(Ctrl+Shift+`)、認識されると思います。

#### VS Code を開く
以下のバッチファイルをプロジェクトのフォルダで開きます。

```bat:vscode.bat&nbsp;(汎用)
@echo off
%~d0
cd %~d0%~p0
code .
```

Pythonインタープリタの選択ができていない場合は、Ctrl+Shift+Pを押して「Pythonインタープリタの選択」を選び、仮想環境のパス`D:\development\python\django\Scripts\python.exe`を選択してください。
候補がない場合は、「Enter interpreter path...」から選択します。

VS Codeのターミナルで仮想環境が認識されていない場合は、いったんターミナルを破棄して(ゴミ箱)、開き直して(Ctrl+Shift+`)みてください。

#### ターミナルを開く
以下のバッチファイルを、仮想環境のフォルダか、その親子辺りに作ります。

```bat:terminal.bat&nbsp;(汎用)
@echo off
%~d0
cd %~d0%~p0
if exist %~d0%~p0venv\Scripts set SCRIPTS=%~d0%~p0venv\Scripts\
if exist %~d0%~p0..\Scripts set SCRIPTS=%~d0%~p0..\Scripts\
if exist %~d0%~p0Scripts set SCRIPTS=%~d0%~p0Scripts\
call %SCRIPTS%activate
echo Python Terminal activated by %SCRIPTS%activate
```

このファイルのショートカットを作って、「リンク先」を以下のように、

```text
C:\Windows\System32\cmd.exe /K D:\development\python\django\practice\terminal.bat
```

「作業フォルダー」を以下のように設定します。

```text
D:\development\python\django\practice
```

ショートカットを開くと、以下のようなターミナルウインドウが開きます。

```text
Python Terminal

(django) D:\development\python\django\practice>
```

# JupyterLab で Python
### JupyterLab 用仮想環境の構築、アクティベート、JupyterLab の導入
`JupyterLab`フォルダに仮想環境を作り、アクティベートします。
カレントディレクトリを移動して、JupyterLab を導入します。

```text
D:\development\python\>virtualenv jupyterlab
~ 略 ~

D:\development\python>jupyterlab\scripts\activate

(jupyterlab) D:\development\python>cd jupyterlab

(jupyterlab) D:\development\python\jupyterlab>pip install jupyterlab
~ 略 ~
```

### 普段使いのショートカット
#### JupyterLab を開く
以下のバッチファイルを、`D:\development\python\jupyterlab`に作ります。

```bat:jupyterlab.bat&nbsp;(汎用)
@echo off
%~d0
cd %~d0%~p0
if exist %~d0%~p0venv\Scripts set SCRIPTS=%~d0%~p0venv\Scripts\
if exist %~d0%~p0..\Scripts set SCRIPTS=%~d0%~p0..\Scripts\
if exist %~d0%~p0Scripts set SCRIPTS=%~d0%~p0Scripts\
call %SCRIPTS%activate
start /min %SCRIPTS%jupyter-lab.exe
```

#### ターミナルを開く
前述のターミナル用バッチファイルを、`D:\development\python\jupyterlab`に作ります。
そのファイルのショートカットを作って、「リンク先」を以下のように、

```text
C:\Windows\System32\cmd.exe /K D:\development\python\jupyterlab\terminal.bat
```

「作業フォルダー」を以下のように設定します。

```text
D:\development\python\jupyterlab
```

ショートカットを開くと、以下のようなターミナルウインドウが開きます。

```text
Python Terminal

(jupyterlab) D:\development\python\jupyterlab>
```

# バッチファイルの使い回し
ここで用意した各種バッチファイルは、環境やプロジェクト毎にコピーして使うと保守が面倒です。
そこで、`D:\development\python\utility`にまとめておいて、

```text
D:\development\python\newenv>mklink /h terminal.bat ..\..\utility\terminal.bat
```

みたいな感じで、プロジェクト毎にハードリンクを作って使い回します。
こうすれば、どれを修正しても全てに反映されます。

# virtualenv でなく venv を使う
使い方によっては、venvで十分な場合もありますね。

## Django
```text
D:\development\python>python -m venv django

D:\development\python>cd django

D:\development\python\django>scripts\activate

(django) D:\development\python\django>pip list
Package    Version
---------- -------
pip        20.2.3
setuptools 49.2.1
WARNING: You are using pip version 20.2.3; however, version 21.0.1 is available.
You should consider upgrading via the 'd:\development\python\django\scripts\python.exe -m pip install --upgrade pip' command.

(django) D:\development\python\django>python -m pip install --upgrade pip
~ 略 ~
Successfully installed pip-21.0.1

(django) D:\development\python\django>pip list -o
Package    Version Latest Type
---------- ------- ------ -----
setuptools 49.2.1  54.2.0 wheel

(django) D:\development\python\django>pip install -U setuptools
~ 略 ~
Successfully installed setuptools-54.2.0

(django) D:\development\python\django>pip install django
~ 略 ~

(django) D:\development\python\django>pip list
Package    Version
---------- -------
asgiref    3.3.1
Django     3.1.7
pip        21.0.1
pytz       2021.1
setuptools 54.2.0
sqlparse   0.4.1
```

## Jupyterlab
```text
D:\development\python>python -m venv jupyterlab

D:\development\python>cd jupyterlab

D:\development\python\jupyterlab>scripts\activate

(jupyterlab) D:\development\python\jupyterlab>pip list
Package    Version
---------- -------
pip        20.2.3
setuptools 49.2.1
WARNING: You are using pip version 20.2.3; however, version 21.0.1 is available.
You should consider upgrading via the 'd:\development\python\jupyterlab\scripts\python.exe -m pip install --upgrade pip' command.

(jupyterlab) D:\development\python\jupyterlab>python -m pip install --upgrade pip
~ 略 ~
Successfully installed pip-21.0.1

(jupyterlab) D:\development\python\jupyterlab>pip install jupyterlab
~ 略 ~
```

# settings.py の設定
## 言語とタイムゾーン
- 以下の既存のシンボルの値を書き換えます。

```py:settings.py
LANGUAGE_CODE = 'ja-jp'
TIME_ZONE = 'Asia/Tokyo'
```

## ログの設定
- 以下を末尾に追加します。
    - `level`や`filename`などは任意に設定可能です。

```py:settings.py
# Logging
from logging import basicConfig, DEBUG, INFO, WARNING, ERROR, CRITICAL
if DEBUG:
    basicConfig(
        level = DEBUG,
        format = '%(asctime)s %(levelname)s %(message)s',
        #filename = 'debug.log',
        #filemode = 'w'
    )
else:
    basicConfig(
        level = ERROR,
        format = '%(asctime)s %(levelname)s %(message)s',
        filename = 'debug.log',
        filemode = 'a'
    )
```

- 上記の設定ですと、`DEBUG = False`に設定した場合、このプロジェクトでは、`D:\development\python\django\debug.log`が出力されます。
    - デフォルトでは、`DEBUG = True`ですので、コンソールに出力されます。
    - 残念ながら、コンソールとファイルに同時に記録する需要は考慮されていないようです。

### ログの出力
```py
from logging import getLogger
logger = getLogger(__name__)

logger.info("information level message")
logger.debug("debug level message")
```

- ログレベルは、デバッグからクリティカルまで5段階のプリセットがあります。
    - 設定したレベル以上で出力したものが記録されます。
    - 例えば、`INFO`に設定すると、`logger.debug()`は記録されなくなります。

# 保守
- Pythonをアップグレードします。

## Pythonのアップグレード
- 必要に応じて、素の環境(≠仮想環境)の記録を取ります。
    - この記事では、`pip`と`setuptools`しかない前提です。

```text
d:>pip freeze >requirements.txt
```

- 新しいバージョンのPythonを[ダウンロード](https://www.python.org/downloads/)してインストールします。
- 続けて、モジュールをアップデートします。

```text
d:>python -V
python 3.9.6

d:>python -m pip install --upgrade pip
~ 略 ~

d:>pip install -U setuptools
~ 略 ~
```

## 仮想環境のアップグレード
- 新しいバージョンのPythonを導入しても、仮想環境は更新されません。仮想環境毎に更新が必要です。
- 以下では、virtualenvでなくvenvを前提にして、Jupyterlabの環境を例に挙げます。

### 仮想環境を更新
- 仮想環境を更新するには、いったん仮想環境を抜ける必要があります。
- 以下の`.\`は、仮想環境のパスを指定しています。

```text
(jupyterlab) D:\development\python\jupyterlab>python -V
Python 3.8.8

(jupyterlab) D:\development\python\jupyterlab>deactivate
D:\development\python\jupyterlab>python -m venv .\ --upgrade

D:\development\python\jupyterlab>Scripts\activate
(jupyterlab) D:\development\python\jupyterlab>python -V
python 3.9.6
```

### モジュールの更新
- インストール済みのモジュールを更新します。
- まずは、更新の必要なモジュールのリストを得ます。

```text
(jupyterlab) D:\development\python\jupyterlab>pip list -o
Package           Version   Latest    Type
----------------- --------- --------- -----
anyio             2.2.0     3.3.0     wheel
attrs             20.3.0    21.2.0    wheel
Babel             2.9.0     2.9.1     wheel
bleach            3.3.0     4.0.0     wheel
certifi           2020.12.5 2021.5.30 wheel
~ 略 ~
```

- 得たリストを加工して、一括更新用のリストにします。

```text:requirements.txt
anyio==3.3.0
attrs==21.2.0
Babel==2.9.1
bleach==4.0.0
certifi==2021.5.30
~ 略 ~
```

- リストを使って一括更新します。

```text
(jupyterlab) D:\development\python\jupyterlab>pip install -r requirements.txt
~ 略 ~
```

## 不要なバージョンを削除
- 使わなくなったバージョンのPythonは、Windowsの設定「アプリと機能」からアンインストールできます。

# 参考記事
以下の記事を参考にさせていただきました。

- [VSCodeでDjangoを使用した仮想環境を構築する(Windows)](https://qiita.com/ays103562/items/6039c0e99b245c4742ce) (Qiita)
- [Python仮想環境とDjango](https://qiita.com/Syoitu/items/54d6d3e57482c1e8ab17) (Qiita)
- [venv --- 仮想環境の作成](https://docs.python.org/ja/3/library/venv.html) (公式ドキュメント)
- [ログ出力のための print と import logging はやめてほしい](https://qiita.com/amedama/items/b856b2f30c2f38665701) (Qiita)
- [Djangoのコンソールにデバッグのメッセージを出力する方法](https://qiita.com/NoriakiOshita/items/7716c6e46338768467eb)
- [ライブラリのためのロギングの設定](https://docs.python.org/ja/3.8/howto/logging.html#configuring-logging-for-a-library) (公式ドキュメント)
- [仮想環境のPythonをバージョンアップする](https://qiita.com/hiron2225/items/419d29ebdad6bdbc7ed1) (Qiita)

どうもありがとうございました。

# おわりに
- 仮想環境のフォルダ名を後から変更するのは困難です。決定は慎重にどうぞ。