メタラーまとんがハイソにやらかすようです

東大理系修士卒JTBCエンジニアのハイソサイエティ(上流階級)な日常

WSL+pyenv+pipenv+VSCodeで令和モダンなpython仮想環境を構築しよう!

ども!AWS認定SAアソシエイトのまとんです。

今までWindowsではAnacondaでPythonを使っていたのですが、そろそろ仮想環境をちゃんと使いこなせるようになろうと思い、構築しました!

TL; DR

Windows10のWSL(Windows Subsystem for Linux)で、pyenvとpipenvを使ってディレクトリごとにPythonの環境を切り分けられるようにした上で、Windows10のVSCodeからWSLのPythonを触れるようにします。

経緯

ひょんなことから友人と一緒にサービスを作ることになりました。

友人はアルゴリズムの開発を担当。僕はAWS Lambdaでサービスデプロイを担当です。

AWS LambdaはPythonのランタイムを好きに選べますが、ライブラリはzipで固めてアップロードする必要があります。

友人の開発環境はAnacondaのPython3.7で、僕のAnacondaはPython3.6。ライブラリの依存関係で苦労するリスクがありました。

そこで、僕のメイン環境を汚さないように、今回のサービスを開発するPythonの環境を切り分けて、ライブラリ群を整理し、AWS Lambdaにデプロイするための準備をしました。

色々調べたところ、最近では仮想環境はpipenvが主流と言っている人が多かったので、pipenvを採用。

IDEは、最近は猫も杓子もVSCodeと言っているので、VSCodeを選択。

Windowsコマンドプロンプトが嫌いなので、WSLのUbuntu上で動くようにしました。

出来上がった環境のイメージ

f:id:highso:20200115015626p:plain

Windows10上でpython環境を立ち上げるのはめんどうなので、WSL上にPython環境を作り、そこにVSCodeからアクセスして、Linuxライクに開発できるようにします。

WSLでは、pyenvとpipenvを組み合わせて、ディレクトリごとにPython環境を切り分けします。

仮想環境の構築やライブラリの管理は全てpipenvで行います。

ただし、pipenvはpython本体のインストールができないので、pyenvでpython本体をインストールします。

pipenvとpyenvは親和性が良く、pipenvで未インストールのバージョンのpythonで仮想環境を作ろうとすると、pyenvが自動的にpython本体をインストールしてくれます。

※ただしWSLでpipenvを使うと不具合があって、結局pyenvで手動でpythonをインストールすることになりました

使用したもの

  • メイン環境:Windows10
  • WSL:Ubuntu 18.04.3 LTS
  • pyenv 1.2.16
  • pipenv 2018.11.26
  • VSCode 1.41.1
  • VSCode extention, Remote - WSL 0.41.7

手順

WSLとpipはインストール済みとする

以前にAWS IoTを試すためにWSLとpython3とpipを導入していました。

WSLの導入手順はこの記事にまとめてあります。

highso.hatenablog.com

結果として、僕のWSLには、python2.7とpython3.6が導入されていました。

前準備

$ sudo apt update

$ sudo apt upgrade

$ sudo pip3 install -U pip

依存関係のあるライブラリをインストール

$ sudo apt install -y 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

WSLにpyenvをインストール

git cloneでpyenvを導入します。

参考:Windows10(WSL)で、2018年的Pythonプロジェクト(①pyenv/pipenvの導入) - Qiita

$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv

$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc

$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc

$ echo 'eval "$(pyenv init -)"' >> ~/.bashrc

$ source ~/.bashrc

$ pyenvで起動することを確認します。

【WSLの不具合】.bashrcが読み込まれないので自動起動を設定

大体のブログ記事にはこの手順が載っているのですが、ここで1点問題が。

~/.bashrcにpyenvのPATHを書いているのですが、WSLでは立ち上げ時に~/.bashrcが読み込まれないようです。

参考:Bash on Windows 起動時に ~/.bashrc が読み込まれない - 今日も窓辺でプログラム

WSL立ち上げごとに$ source ~/.bachrcしてもよいですが、面倒です。そこで、~/.bash_profileに書けば解決しました。

$ touch ~/.bash_profile

$ nano ~/.bach_profile

以下を書き込んで保存します。

if -f ~/.bashrc ; then
. ~/.bashrc
fi

これでWSLを再立ち上げしても$ pyenvが効くようになりました。

pipenvの基本的な使い方

・pipenvでインストールできるpythonのバージョン一覧表示

$ pyenv install --list

・例:python 3.7.3をインストールしたいとき

$ pyenv install 3.7.3

・例:Anacondaをインストールしたいとき

$ pyenv install anaconda3-4.3.1

※Anaconda環境は数値計算ライブラリをまとめて導入できるので便利ですが、Anacondaが共存すると様々な問題が生じがちなので、pyenvでの使用はオススメしません。

詳しい人によると、「小さいもの(pyenv/pipenv)で大きいもの(Anaconda)を入れるのは、おかしい」とのことです。

・pyenvでインストール済みのバージョンを確認

$ pyenv versions

Pythonのバージョンを切り替える

$ pyenv global 3.7.3

この後に$ pythonと実行すると、3.7.3が立ち上がるようになります。

・現在のバージョンを確認

$ pyenv --versions

・特定のディレクトリ内のみバージョンを切り替えたいとき

好きなディレクトリに移動してから、

$ pyenv local anaconda3-4.3.1

そのディレクトリの中で$ pythonを実行すると、anaconda3-4.3.1が起動するようになります。

これでディレクトリごとにPythonのバージョンを使い分けることができるようになりました!

WSLにpipenvをインストール

pipenvはpipで導入できるのでラクチンです。

$ sudo pip3 install pipenv

 pipenvの基本的な使い方

・プロジェクト用の新規ディレクトリを作って、仮想環境を作成(初期化)

$ mkdir project && cd project

~/project$ pipenv install # 仮想環境を作成

これでprojectディレクトリ直下にPipfileとPipfile.lockという設定ファイルができます。これらに仮想環境の情報が記載されていきます。

試しにProfileの中身を見てみます。

~/project$ cat Profile

source

name = "pypi"

url = "https://pypi.org/simple"

verify_ssl = true

[dev-packages]

[packages]

[requires]

python_version = "3.6"

pythonのバージョンが3.6で仮想環境が作られたことが分かります。

・仮想環境に入って作業する

~/project$ pipenv shell 

(project) XXX@YYY:~/project$

exitで抜ける

シェルの先頭に(project)がついて、仮想環境に入っていることがわかります。

ここでpythonなど実行すると、仮想環境で実行できます。

・仮想環境に入らずに、1行だけコマンドを直接実行

~/project$ pipenv run  <コマンド> 

・仮想環境を削除して、設定ファイルも削除

~/project$ pipenv --rm

~/project$ rm Pipfile

~/project$ rm Pipfile.lock

Pythonのバージョンを指定して初期化

pipenvで一番使いたい機能はこれかと思います。

$ pipenv install --python 3.7

もし、3.7がインストールされていなければ、pyenvが自動的にインストールしてくれます。

【WSLの不具合】pipenv初期化時のエラー対策

WSLで $ pipenv install --python 3.7などとバージョン指定すると、以下のようなエラーを吐くことがあります。

TypeError: write() takes exactly one argument (3 given)

どうやら、なぜかWSLではなくWindows側のpythonを呼びに行っていることが原因のよう。

issueには上がっているようですが、根本解決はされていない模様。

参考:[python] WSLのpipenv install時になぜかWindows側のpythonが呼ばれる件 - Qiita

その場しのぎの解決策として、pipenvでバージョン指定するときは、まずpyenvで所望のバージョンをinstallしてから、フルパスで指定してあげるとよいです。

$ pyenv install 3.7

$ pipenv install --python=/home/<ユーザー名>/.pyenv/versions/3.7.6/bin/python

本当はpipenv実行したときにpyenvが自動的にインストールしてくれればスマートなんですが、WSLではできないようです。残念。

pipenvでライブラリインストール

普通のpipと同じ感覚でできます。

projectのディレクトリで実行します。

$ cd project

$ pipenv install <ライブラリ名>

 仮想環境に導入したライブラリの依存関係は、Pipfile.lockerに記載されていきます。

・ライブラリのバージョンを指定

$ pipenv install nose=1.3.7

・仮想環境にインストールされたライブラリの一覧を確認

$ pipenv run pip freeze

以上で、pyenvとpipenvを使って一通りのことはできるようになりました。

VSCodeをインストール

次に、コーディングの利便性向上のために、VSCodeを導入していきます。

WSLはCLIしかありませんので、ちょっとUbuntuを使う際には便利ですが、がっつりコーディングする際はモダンなIDEを使った方が効率が良いでしょう。

VSCodeインストーラーは、普通に公式サイトからダウンロードできます。

Visual Studio Code - Code Editing. Redefined

Stable buildをインストールしました。

VSCodeにextentionを入れる

VSCodeをインストールして立ち上げたら、左バーのExtensionsから、Remoteで検索します。

VSCodeからWSLを触るExtensionsとして、Remote Developmentを挙げているブログ記事がありました(参考:VSCode Remote WSLでPython開発環境構築 - Qiita)が、

「WSLが入っているみたいだから、Remote - WSLがオススメだよ!ぜっっったいにオススメだよ!」と、VSCodeからメンヘラのごとく強い通知が来たので、Remote- WSLをインストールしてみました。

f:id:highso:20200115013249p:plain 

画像引用元:VSCode Extensions, Remote - WSLのアイコン

ペンギンのアイコンが可愛い。たぶんこいつがメンヘラ。

WSLからVSCodeを開く

WSLで、実行したい仮想環境のディレクトリで1行実行します。(VSCodeインストールしてから再起動は必要かも)

$ code .

これでVSCodeが立ち上がります。左下にWSLと表示されていればOKです。

VSCodeで各種設定

WSLから開いたVSCodeで設定します。

PythonのExtensionを導入

ExtensionsからPython extension for Visual Studio Codeをインストール

pipenvを使用する設定

View -> Command Pallete -> "Preferences: Open Workspace Settings"を入力してエンター

右上の「Open Settings (JSON)」アイコンをクリック

settings.jsonのエディタが立ち上がるので、以下のように記述してCtrl+Sで保存。

{
    "python.pythonPath""/home/<ユーザー名>/.local/share/virtualenvs/newproject-HVu4x-gG/bin/python",
    "files.watcherExclude": {
        "**/.venv/**"true
    }
}

これでpipenvのインタープリタを使えるようになりました。

インタープリタ設定

てきとうに「aaa.py」とか作って、「print('hoge')」とか書いておきます。

F5で実行できます。ここでインタープリタとしてpipenvのものを選択します。

これで、pipenvで作った仮想環境で、VSCodeを使って開発できるようになりました!!

VSCodeのterminalでWSLを直接いじることができるので、もうWSLのターミナルを使う必要もほぼほぼ無くなりました。

VSCode最高!!!

f:id:highso:20200115020852p:plain

まとめ

WSLでpyenvとpipenvを使うと、少々不具合が残っているものの、対処法さえ分かれば不自由なく仮想環境が作れました。

VSCodeはWSL専用のExtensionをサポートしていて、シームレスに開発できる優秀なIDEです!

おわりに

この環境を自分のPCで立ち上げて、フンフーン♪と鼻歌を歌いながら次の日に出社すると、会社で先輩がPyCharmを使っていたので、僕も会社ではPyCharmを使うことになった。モヤっとした。

 

以上、メタラーまとんでした。

ではでは。

今までに作った作品を紹介

highso.hatenablog.com

highso.hatenablog.com

highso.hatenablog.com

highso.hatenablog.com