Pythonにおける仮想環境「venv」について

# 1.はじめに

私は長年javaを用いたシステム開発を行ってきましたが、pythonを学ぶにあたって大きな壁とも言える違いに遭遇しました。それは、外部ライブラリ（モジュール）の扱いについてです。javaでは外部のライブラリは一般的にはjarと呼ばれるファイルで提供され、コンパイル時もしくは実行時にファイル名を指定する必要があります。

~~~
$ java -cp .\;.\lib\commons-lang3-3.9.jar HogeHoge
~~~

手間ですが、実行するアプリケーションによって必要となるライブラリは異なるので、自然な考え方だと思います。

一方Pythonでは、pipといわれるパッケージ管理ソフトを用いてライブラリの導入を行ないます。その際、何も手当を行わないとpython自体にライブラリが導入されます。つまり、複数のアプリケーションを同じ環境で動かす場合において、そのすべてのアプリケーションでライブラリが共有されることになります。

~~~
$ python -m pip install numpy
~~~

これは、便利なようでもあります。いちいちアプリケーションごとにライブラリを準備するよりも。ですが、ライブラリのバージョンが異なると動かないということは日常的にあるため、アプリケーションごとに動作確認が取れているものを導入したいことがほとんどです。もちろん、最新バージョンのライブラリで動くように修正できることが理想ではありますが現実的ではないと思います。

そういったことを回避する方法はいくつかあるのですが、今回はpythonの仮想環境を用いる方法を紹介したいと思います。

pythonはその長い歴史の中で、いくつかの仮想環境が開発されてきました。中でも、よく見かけるのは**pyenv＋virtualenv**と**venv**の二つだと思います。

私はたまたま**pyenv＋virtualenv**を最初に触ったのですが、Windowsで改めて環境を作ろうとしたとき、Windowsでは**pyenv**を使用できない[^1]ということを知り、軽く絶望しました。。。一方、後から知った**venv**はpython標準として提供されており、実行環境に依存しません。そのため、今では可能な限りvenvを使うべきであると考えています[^2]。

本稿ではそういった理由から**venv**についての使い方を紹介いたします。


# 2.前提

本稿では以下を前提とします。

* python3.7を対象とする（Anacondaなどではなく純正[^3]）

# 3.venv環境構築

まず、pythonのコードを配置するためのフォルダを作成します。（このフォルダをプロジェクトフォルダと命名します。）

~~~
■linux
$ mkdir pj
$ cd pj

■Windows
> mkdir pj
> cd pj
~~~

プロジェクトフォルダ直下にて仮想環境を構築します。

~~~
■linux
$ python -m venv .venv 

■Windows
> python -m venv .venv 
~~~

このコマンドを実行すると、プロジェクトフォルダ配下に「.venv」というフォルダが作成され、いろいろなファイルがコピーされてきます。
ですが、そのままでは有効化されません。有効化するためには以下コマンドを実行します。

~~~
■linux
$ source .venv/bin/activate 

■Windows
> .venv\Scripts\activate.bat
~~~

これで、仮想環境が整いました。この状態でpipコマンドを用いてライブラリを導入すると、作成した仮想環境にライブラリが導入されます。
なお、仮想環境を無効化するためには、以下コマンドを実行します。

~~~
■linux
$ deactivate 

■Windows
> deactivate
~~~


ただし、仮想環境が有効されるというのは、コマンドプロンプトであればそのプロンプト内だけです。OS全体に有効化されるわけではない点に気を付けてください。また、サーバに導入する場合は、起動スクリプトに上述のactivateコマンドを呼び出す必要があります。[^4]


# 4.実験

activate後に外部ライブラリを導入して、他の環境に影響していないことを確認してみましょう。同一プロジェクトフォルダ内に複数の仮想環境を導入することも可能ですので、今回その方法を用いることにします。

## 4.1. プロジェクトフォルダ作成と仮想環境２セット準備

~~~
$ mkdir sample_pj
$ cd sample_pj
$ pip freeze

$ python -m venv .venv1
$ python -m venv .venv2
~~~

「pip freeze」はすでに導入されているライブラリの確認コマンドです。何も入っていなければ空行が表示されると思います。

## 4.2. venv1環境にnumpyを導入

~~~
$ source .venv1/bin/activate 
(.venv1) $ pip install numpy
(.venv1) $ pip freeze
numpy==1.17.1

~~~
バージョン番号は異なるかもしれませんが、numpyがインストールされると思います。

## 4.3. 他の環境にnumpyが導入されていないことを確認

~~~
(.venv1) $ deactivate 
$ pip freeze

$ source .venv2/bin/activate 
(.venv2) $ pip freeze

~~~

venv1環境に導入したnumpyが他の環境に導入されていないことを確認できると思います。


# 5.プロジェクトフォルダ共有における注意点について
プロジェクトフォルダをgitなどで共有する際は、.venvの中身は共有対象から外すべきです。一方で、外部ライブラリについて何を導入すればよいかが分からなくなってしまうので、**requirements.txt**というものを用意しておきます。このファイルは`pip freeze`の結果そのものです。

~~~
(.venv) $ pip freeze >  requirements.txt
~~~

環境を構築する際は、venvで仮想環境を構築したのち、pipコマンドにこのファイルを食わせることで必要なライブラリが導入されます。

~~~
(.venv) $ pip install -r requirements.txt
~~~


# 6.おわりに
pythonにおける仮想環境venvについて、簡単な使い方をご紹介しました。本来、言語を勉強するにあたって、仮想環境などは本質的なことではないのですが、既に他の言語で開発経験がある方であれば、環境から本番環境などにリリースをするにあたって、どうやって環境を構築していこうかというのは、ごく普通の疑問だと思います。その疑問に少しでも答えることができていれば幸いです。



[^1]: Windows Subsystem for Linuxやdockerなどを用いてLinux環境をWindows内に用意することで実現はできますが、いろいろ手間がかかったり制限があります。そもそも、最終的な実行環境がLinuxであることが多いので、Linuxを用いて開発を行うべきではありますが、開発環境としてWindowsを用いざるを得ないというケースも結構あります。

[^2]: 複数バージョンのpythonを使い分けるという特殊なケースの場合は、venvではなくpyenvの活用も検討した方が良いと思います。

[^3]: なぜAnacondaを用いないかというと、「実行環境はなるべくシンプルであるべき」という思想であるからです。Anacondaなどを用いると、既にいろいろなライブラリが導入されているので、めんどくさい環境構築をしなくてもよいようなのですが（食わず嫌いで使ったことがないです。。。）、逆に全くどんな環境なのか把握できないという状況になります。例えば、ライブラリにはセキュリティホールが含まれているケースが多々あるのですが、自分の開発したシステムにそのライブラリが含まれている場合に、影響調査をしなければなりません。一人で開発しているのであるならば、使っているかどうかを把握することは難しくないかもしれませんが、複数人で開発している場合は、どこで何が使われるか把握することは困難です。ましてや人が作ったものを引き継いだ場合は、調査せずに把握はできません。その調査の影響範囲をなるべく狭くしたいので、使ってもいないライブラリは入れておきたくないのです。

[^4]: VSCodeを使用している場合、エディタがvenvを検知し自動でactivateしてくれます。今、世界で一番ホットな開発ツールなので使って損はないはずです。