# AI 開発環境構築(主に windows10) - pipenv, pyenv を使った仮想環境 -
###### tags: `旧バージョン`, `素材`, `ai`, `handson`, `仮想環境`, `python`, `vs code`
## :school: ハンズオンの対象とする人、その目的
AIをやってみようと aidemy などの学習用のコンテンツを閲覧して、雰囲気はわかったけれど、次は何をしたらいいだろう、と思っている人。AIを活用して課題を解決できそうなアイデアを持っているけど、その有効性を確認するには、何か実際に動くモノがあったほうがよさそうだが、それってどうやって実現すればいいのかわからず止まっている人。
そのような初学者、初心者を対象に、そのとっかかり、本格導入への呼び水となりますように、まずはそういうことを実現するための開発環境を整えるために。ネットで検索すればすぐにわかることはなるべくそちらに任せて、調べてもすぐに適切な解決方法を見つけにくい点をピックアップしてるつもりです。
## :white_circle: 内容とゴール
vs code、python、python の環境分離ツールをインストールし、その使い方を説明します。
AI開発環境の構築に嵌まると時間を取られます。
Qiita などで初学者向けに(初学者が作成した)導入に関する解説ページを見つけることができますが、参考とするページの選択を誤ると相当の時間をロスります。そこでまずは、python の開発環境においての基本的な考え方やルール、それらを実践するためのツール(主に仮想環境に関するもの)について説明します。
**必要なソースコードとパッケージ情報があれば、すぐに動かすことができるようになっている**
のがゴールです。
## 開発 editor 環境、 visual studio code
2020年1月現在、python の開発で使うeditor環境というと、たぶん pycharm と vs code の2大勢力だと思います。それぞれに長所、短所があるようですが、ここ最近の勢いと、完全無料、また社内での利用者数が多数、特にpycharm の急先鋒山路さんが退社されたということで、vs code でおこないます。
vs code インストールのオフィシャルなページはこちら ⇒ https://code.visualstudio.com/docs/setup/windows
https://code.visualstudio.com/docs/python/python-tutorial
vs code のインストール、インストール後の vs code 上での python extension のインストールについては [こちら](https://www.kkaneko.jp/tools/win/vscode.html)などを参考にお願いします。
extension は色々便利なモノがあるようです。これは便利、というものがあれば、ぜひ、slack の usr_pythonista、usr_machinelearning などに挙げてください。今回は pythonとpython for VSCode が必要です。
### python を インストール
windows環境でのインストールについては、https://www.python.jp/install/windows/install_py3.html
を参照ください。
このpython は システムにインストールされました。global にインストールされた、という言い方もします。特定の仮想環境(後述)を指定していない状態でpython を実行すると、これが使われます。
python を インストールすると、インストールしたフォルダ下に、pip も同時にシステムにインストールされます。pipは linux のパッケージ管理に使われる apt みたいなイメージです。
powershell から
``` python
> gcm pip
```
とすると、pip のパスが表示されます。このpipも global な環境にインストールされています。このpipはこれまでパッケージ管理で主に使われてきたツールで、現在も利用者は最多かもしれません。しかし今後は pip から pipenv へ移行が進みpipenv が主に使われていきそうです。
## 環境分離とは
環境分離とはどういうものか、なぜ導入するのか、を説明します。

開発環境を構築し、その後も開発を継続してく中で、python 本体のバージョン管理と、配布されるパッケージ(numpy, matplotlib, tensorflow などなど)のバージョン管理、大きく分けてこの2種類のバージョン管理をする必要にしばしば迫られます。「このプロジェクトは python3.6、○○のパッケージ ver.x1から ver.x2 で動作します」などと、python本体や使われているパッケージにバージョンの指定がされてあることが多いからです。
そこでプロジェクトごとに、python 本体のバージョンと各パッケージのバージョンの組み合わせをまとめたものを仮想環境と呼んで区別し、管理する仕組みがあります。
リリース、デプロイされる際にテストはされているでしょうが、開発に使った様々なパッケージの、異なるバージョンの組み合わせ全てに関してまでテストをおこなうことは現実的ではないため、このバージョンの組み合わせで正常に動作することを確認しています、という情報をもとに、利用する側も、その環境を丸々再現して動かしたい、などの要求に応えるためです。
例えばあるアプリケーションは次のようなバージョンの組み合わせの環境で作ってテストされ、
python 3.7,
packageA 2.4
packageB 1.5
:
:
別のアプリケーションは次のようなバージョンの組み合わせの環境で作ってテストされ、
python 3.6,
packageA 2.3
packageB 1.3
:
:
となっているため、利用する側も、アプリケーションごとに個別に環境を用意し、動作させます。
これが python の環境分離です。
****環境はシステム(global)と local(仮想環境) に分かれます。global な環境では、pyenv を使って環境間を移動し、numpy などのモジュールのglobalな環境へのインストールは pip を使います。
一方、localな(仮想)環境では、環境間の移動はpipenv でおこない、モジュールのインストールも pipenv でおこないます。****
デフォルトだとログインしているユーザーのHOME(windows では c:\user\xxx)下に仮想環境が作成されます。
仮想環境をまとめて1か所で管理する、というやり方です。
好みの問題でもありますが、vs code で開いているフォルダ下に個々の仮想環境が作られるようにした方がわかりやすい、という人は、環境変数
```
PIPENV_VENV_IN_PROJECT=true
```
を設定してください。windows だとユーザー環境変数で変更してください。変更後、vs code を再起動で設定が反映されます。
web を見てると、この設定をしている人のほうが多数派のように見えます。私もこの設定にしてます。とりあえず本日はこの設定を有効にしておいてください。
:memo: WORKON_HOMEを指定すると、指定した箇所にまとめて仮想環境を作成してくれます。 仮想環境を作成する場所をまとめたい時は WORKON_HOME=~/.virtualenvs などとするとよいです。
このように、複数の仮想環境をまとめて1つのフォルダ下に管理する、というやり方は、全ての作業をターミナルからコマンド入力でおこなう、というやり方には向いていると思います。今回使うvs code のように folder を作業の対象としてプロジェクトのように扱うツールでは、仮想環境も vs code で指定した folder 下に置くのがわかりやすく、使いやすくなるのだと思います。
### 複数のバージョンの python を管理する pyenv の導入
windows用の pyenv は https://pypi.org/project/pyenv-win/ にあります。
windows環境での導入については
https://pypi.org/project/pyenv-win/#pyenv-win-commands
global な環境では、pyenv を用いて複数のバージョンのpython をインストールし、pythonを切り替えて使うことができます。一方、仮想環境では、pipenv で、どのバージョンの python を仮想環境のpythonとするかを選択する(選択すると仮想環境下に選択したpython の本体が置かれる)、ということをします。したがってシステムにインストールしてないversion のpython をpipenv で指定して仮想環境に導入することはできません。
:memo:Ubuntu では、 https://github.com/pyenv/pyenv-installer 参照。
サラのシステムだと前準備はけっこう面倒でした。以下のものを sudo apt install します。詳細は[こちら](https://qiita.com/shigechioyo/items/198211e84f8e0e9a5c18)を参照。
```
gcc make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
```
> .profile を編集して install した pyenv にPATHを通す
> \> pyenv install --list #install できる python の全version表示
> \> sudo pyenv install 3.8.1 #python 3.8.1 をシステム(global)にinstall
:memo: pyenv で システム(globalな環境)に複数のpython をインストール
例えばシステムに 3.7.3 と 3.8.1 がinstallされているとする。3.8.1 に numpy をインストールするには
> \> pyenv global 3.8.1 #3.8.1 を global に設定
して、global な環境にモジュールを導入するには pip を使います。仮想環境へのモジュールの導入は pipenv(次節参照)を使います。global 環境へのモジュールのインストールは pipenv ではなく、pip を使うようです(大事なことでややこしいので2回書きました)。
> \> pip install numpy --user #global(今は3.8.1)に numpy を インストール
:memo: 社内LANで proxy を使っている環境では、
```
"Not supported proxy scheme None"
```
のような proxyに関わるエラーによりインストールできない場合があります。その場合、環境変数の設定で
set HTTP_PROXY=http://proxy.ad.toa.co.jp:8080
set HTTPS_PROXY=http://proxy.ad.toa.co.jp:8080
set http_proxy=http://proxy.ad.toa.co.jp:8080
set https_proxy=http://proxy.ad.toa.co.jp:8080
set all_proxy=http://proxy.ad.toa.co.jp:8080
set ftp_proxy=ftp://proxy.ad.toa.co.jp:8080
set no_proxy=localhost,127.0.0.1,192.168.1.1
set ALL_PROXY=http://proxy.ad.toa.co.jp:8080
set FTP_PROXY=ftp://proxy.ad.toa.co.jp:8080
set NO_PROXY=localhost,127.0.0.1,192.168.1.1
と設定すると、うまくいく場合があります。
### 仮想環境管理ツール=pipenvをシステム(global 環境)へ導入(Windows10)
global な環境に標準で(pythonを最初にシステムにインストールしたときに勝手に)インストールされる)pipを使って、global な環境へ (pipの後継)pipenv をインストールします。
前述のとおりpython インストール時にpip は同梱されているので、 vs code の TERMINAL で、
```
> pip -V
```
とすると、pip が使えるようになっていれば
```
pip 19.3.1 from c:\program\python\python37\lib\site-packages\pip (python 3.7)
```
などのように、pip の versionなどの情報が表示されますので、
```
> pip install --user pipenv
```
とすれば、vs code の TERMINALから見える 環境変数 $HOME 以下にpipenv が install されます。 どこにインストールされたかを正確に知るには、TERMINALで
```
> python -m site --user-site
```
を実行して、ユーザーのベースバイナリディレクトリを見付けてください。
例えば私の場合、
```
> python -m site --user-site
C:\Users\toa19895\AppData\Roaming\Python\Python37\site-packages
```
となっています。pipenv は この site-packages を Scripts に変えた場所にあります。確認するには TERMINALで
```
> gcm pipenv
```
してください。うまく確認できない場合は、パスの設定ができてない可能性あります。環境変数でパスを確認してみてください。
これで、システム(globalな環境)に、python3, pip, pipenv がインストールされました。
### ubuntu では
```
> sudo pip3 install pipenv
```
これで、/usr/local/bin/pipenv が置かれます。
また、例えば全ユーザー向けに python3.7.4 をinstall するには
```
$ wget https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tar.xz
$ tar xvJf Python-3.7.4.tar.xz
$ cd Python-3.7.4
$ ./configure --enable-optimizations
$ make
$ make install
```
で、default では /usr/local/bin 下に install されます。
### 仮想環境を整える
この状態で、いよいよ仮想環境を作っていきます。
まずは、ファイルエクスプローラなどで適当なフォルダ(例えば c:\Users\toaxxxx\handson1 など)を作成します。そして vs code で [open-folder-handson1] して、仮想環境を作るフォルダとして作成したフォルダを指定します。
TERMINAL で、カレントディレクトリが指定したフォルダになるはずです。
環境変数の設定も確認しておいてください。
```
PIPENV_VENV_IN_PROJECT=true
```
この状態で、TERMINALで
```
> pipenv install # version を指定せず
```
します。すると、指定した仮想環境フォルダ下に.venv というフォルダが作成されて、その下にpython, pip他のツールがインストールされます。このとき install される pythonは system にインストールされているpython のバージョンになります。それ以外の例えば3.8.1 を仮想環境化で使いたいときは(pyenv によってシステムに3.8.1がインストールされていれば)
```
> pipenv --python 3.8.1 # version を指定
```
ただし、この段階では、仮想環境と指定したフォルダに python, pip他のツールがインストールされただけで、仮想環境下にいるわけではありません。試しに TERMINAL で
```
> gcm python
```
すると、globalにインストールした python のパスが表示されるはずです。
仮想環境下に移動するには、
```
> pipenv shell
```
するのが、pipenv 本来のやり方なのですが、windows10 で powershell を使うと、そのことがどこにも明示されません(ubuntuの標準ターミナルである bash では、プロンプトに仮想環境のフォルダ名が出る)。そこで、それが分かりにくく気に入らないという人は
```
> .venv\Scripts\activate.ps1
```
してください。これで[open-folder]で指定した仮想環境に移動したことになります。プロンプトに現在の仮想環境に指定したフォルダ名が表示されそのことを実感できます。仮想環境を抜けるには、
```
> deactivate
```
します。こうするとグローバルな環境に移動したことになります。
さて、今の状態は、システム(globalな環境)には、python3, pip, pipenv がインストールされています。仮想環境handson1 には、python3, pip,がインストールされていて、(deactivate してなければ)現在位置は仮想環境 handson1下です。
:memo: activate.ps1 と pipenv shell の違いですが、pipenv shell は、実行したときのメッセージにもありますが、新たにシェルを起動するようです。仮想環境下に入るときのコマンドは、PATH変数を書き換えたりしているので、pipenv shell で新たにシェルを立ち上げて仮想環境に入り、deactivate で抜けても、PATH変数は書き換えられたままの状態です。ですので、pipenv shell で仮想環境下に移動して、そこから抜けるときは、
```
> exit
```
するのが、筋かと思います。
:memo: pipenv の更新には、
```
> pip install --user --upgrade pipenv
```
をTERMINALから実行します。
* pipenv インストール
https://pipenv-ja.readthedocs.io/ja/translate-ja/install.html
https://fereria.github.io/reincarnation_tech/10_Programming/00_PG_setup/pipenv_statup/
* pipenv 運用解説
https://pipenv-ja.readthedocs.io/ja/translate-ja/basics.html#general-recommendations-version-control
### だいぶややこしいのでここまでを整理します
**まずシステムにpythonをインストールしました。このとき同時に pip もインストールされます。pyenv, pipenv をglobalにインストールしました。pyenv を使ってバージョンが異なる複数のpython をシステムへインストールしました。その中からどのバージョンをシステム標準とするか、選択することができます。pipenv を使って仮想環境を作り、そこへ様々なモジュールを pipenv を使ってインストールしました。仮想環境間の移動も pipenv でできます。**
### 仮想環境の切替
面倒ですが、これが vs code が統合開発環境ではなく、エディタだからでしょう。
* vs code で [file] - [open folder] で folder を選択
* vs code 左下の "Python 3.7.2 64bit('.venv':virtualenv) をクリック、あるいは
ctrl-shft-p で Python:Select Interpreter して所望の python 本体を選択
* vs code のTERMINAL で、
``` python
> .venv\Scripts\activate.ps1
あるいは
> pipenv shell
```
:memo: power shell で activate.ps1 したときに
``` python
仮想環境folder/.venv/Scripts/activate.ps1 を読み込むことができません
```
のエラーメッセージが出たら、 power shell を管理者権限で起動してから、
``` python
PS> Set-ExecutionPolicy RemoteSigned
```
してください。
https://qiita.com/Targityen/items/3d2e0b5b0b7b04963750
### 切替えた仮想環境下へのパッケージのインストール
再掲しますと、今の状態は、システム(globalな環境)には、python3, pip, pipenv がインストールされています。仮想環境フォルダ handson1 には、指定したバージョンのpythonがインストールされていて、(deactivate してなければ)現在位置は仮想環境下です。スタート状態です。まずはこれは好みですが、global にインストールしてある pipenv を使って仮想環境下に pipenv を入れます。
```
handson1> pipenv install pipenv
```
とすると、選択した仮想環境folder/.env の下に pipenv パッケージが追加インストールされます。
さらに必須の numpy もインストールしてみましょう。
```
handson1> pipenv install numpy
```
ここで、仮想環境下に作られている Pipfile, Pipfile.lock を開いてみます。
pipfile には global 環境にインストールされた pipenv を使って仮想環境にインストールしたpipenvとnumpy が[package]
の項目に追加されています。
Pipfile
~~~
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
[packages]
pipenv = "*"
numpy = "*"
[requires]
python_version = "3.7"
~~~
pipenv では、pipfile, pipfile.lock に、「利用しているパッケージとそのバージョン情報」が記されているので、別の仮想環境と全く同じ仮想環境をコマンド一発で再現できます。
別の仮想環境のルートフォルダ(例えば c:\Users\toaxxxx\handson2など)を作成して、handson1 の環境を再現してみます。
vs code で [open-folder] して、 handson2 を選択します。
```
> pipenv install
```
pipenv はglobal な環境にインストールしたものです。pathが通っていなければエラーが出ますので、ベースバイナリフォルダのsite-packages を Scriptに変えた場所にあります。
とすると、pipenv は pipfile を参照して、コピー元の仮想環境と同一パッケージ群を含んだ環境(各パッケージのバージョンは最新)を再現します。このとき、インストールされた各パッケージのバージョンでpipfile.lock は更新されます。
また、各パッケージのバージョンまでをコピー元と合わせたい(pipfile.lockも参照させたい)場合は、
```
> pipenv sync
```
とするか、
```
> pipenv install --ignore-pipfile
```
とします。
vs code python での pipenv の使い方の解説動画が英語版ですがこちらにあります。
(日本語での詳しい解説をまだ見つけれていません)
https://www.youtube.com/watch?v=K2fNEoZfuy8
## 付録
### vs code の ワークスペースについて
[こちら](https://prius.cc/itya/20181218_vscode-workspace) に記述があります。
### 仮想環境を取り扱うややこしいツールたち
仮想環境を扱うツールには色々あって、例えば pyenv, pipenv, venv(旧称 pyvenv), virturalenv, pip, などなど、python なので、p がついていて、環境に関するツールなのでenv が付きがちですし、仮想なのでvもついたりして、なんとなく似たような字面になって、ややこしくなっています。pyvenv は今はvenv となっていますが、ほとんど嫌がらせかと思ってしまいます。それぞれの使い方を説明しているページはたくさんありますが、ツールの比較をしているところはあまりないのも、混乱しやすい一因のように思います。
| | インタプリタ切替 | (仮想)環境切替 | パッケージインストール|
| -------- |:--------: |:--------: |:--------: |
|pyenv | ○ | △(systemのpythonのみ)
|virtualenv | ○ | ○
|pip | | | ○
|venv(旧称pyvenv) | | ○
|pyenv-virtualenv | ○ | ○
|virtualenvwrapper | ○ | ○ | ○
|Anaconda | ○ | ○ | △
|pipenv | ○(pyenv) | ○ | ◎
:memo: virtualenv は python3.3 以降、Python公式が提供する仮想環境マネージャであるvenv として取り込まれた。
また、このややこしくなった経緯について、[こちら](https://www.m3tech.blog/entry/python-packaging) に解説がありました。
### 結局どれを使えばいいか?
https://qiita.com/KRiver1/items/c1788e616b77a9bad4dd
http://www.zopfco.de/entry/2017/04/03/233811
などを読むと、主流のpip+virtualenv, pyenv を使った管理から、その環境での使いにくさを解決した pipenv への移行を勧めているサイトをいくつも見つけることができます。そのことについては [こちら](https://techblog.zozo.com/entry/pipenv-make-it-easy-to-manage-dependencies-in-python) に言及があります。
ただ、従来のpip+virtualenv, pyenvを使ったやり方で問題になるケースは、かなり使い込んだレベルでの話のようで、多くの人が問題にしているわけではなく、全面的に移行が進んでいる、というわけではなさそうです。
しかしこれから python で機械学習開発を始めるのならば、新しめの pipenv を使うことにしました。また、現在 pipenv を使わずに開発を進めている方も、これを機に pipenv への移行を検討してみてください。
### WSLとの連携
windows10 環境では、vs code インストール後、TERMINAL は powershell が起ち上がっています。LINUXやcygwinで好みのSHELLを使ってる人には、powershell を使うことがストレスになることがあります。このため、WSLと連携させて vs code で使う対話シェルをお好みのshell で、という設定方法が色々なページで紹介されています。 cygwinとの連携は、今日現在まだ完全ではないようで、WSLとの連携が勧められているようです。
## gitとの連携