Pythonの仮想環境チョットワカリタカッタ


仮想環境とは?

ふと気になったので調べてみた。多分パスをいじってるんだろうなーって思ってたけど、改めて確認したかった。
仮想環境の作り方、使い方は書いてあるけど、結局中で何が行われてるのか気になるという人向けいるのかそんな人?

結局何してたの?

パスを書き換えていました。(予想通り)

そもそもPATHって?

プログラム(実行可能ファイル)は本来フルパスを指定しなければ実行できません。
フルパスとは、Windowsでは、C:\で始まるデータの保存場所を示す文字のことを指します。

いちいちプログラムの保存場所を覚えたり、使うたびに探すのは非効率的。
そのため、よく使うファイルの場所は一箇所にまとめておくと効率的で嬉しいですよね。
それが環境変数PATHです。

以下のコマンドを実行して出力されたものが、PATHと呼ばれているものの実体です。

(windows)  > echo %PATH%
(linux)    > echo $PATH

当方の環境だと、以下のような感じです。
出力の結果は人によって変わります。以下ではLinuxで説明していきます。

~$ echo $PATH
/opt/ThirdParty-6/platforms/linux64Gcc/gperftools-svn/bin:/opt/paraviewopenfoam56/bin:/home/cuz/OpenFOAM/cuz-6/platforms/linux64GccDPInt32Opt/bin:/opt/site/6/platforms/linux64GccDPInt32Opt/bin:/opt/openfoam6/platforms/linux64GccDPInt32Opt/bin:/opt/openfoam6/bin:/opt/openfoam6/wmake:/home/cuz/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

例えば上の環境の中の/usr/binの下のpythonを出力すると

$ ls | grep python
dh_python2
dh_python3
python
python2
python2.7
python3
python3-config
python3.6
python3.6-config
python3.6m
python3.6m-config
python3m
python3m-config
x86_64-linux-gnu-python3-config
x86_64-linux-gnu-python3.6-config
x86_64-linux-gnu-python3.6m-config
x86_64-linux-gnu-python3m-config

さらにこの中のpython3.6のファイルのタイプを調べてやると・・・

$ file python3.6
python3.6: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=09148930900f465f0cb964452b0ac22986fae752, stripped

要するに実行可能ファイルであることがわかります。
いつも、シェル上で我々が単純にpython3と打ち込んだときに、きちんとPythonが実行されるのはPATHを通しているからなんですね。

じゃあ仮想環境は何をしてるの?

pipenvで説明を行いますが、別の仮想環境もやってることは変わらないと思います。

仮想環境を作成すると、カレントディレクトリもしくは所定の場所に仮想環境で使用するPythonやライブラリのインストールされるディレクトリができます。
当方の環境だと、/home/.local/share/virtualenv/test-tJa6NcU0/という場所に作成されました。

そのディレクトリを開くと、下記のようになります。

 .
├── bin
│   ├── activate
│   ├── activate.csh
│   ├── activate.fish
│   ├── activate.ps1
│   ├── activate.xsh
│   ├── activate_this.py
│   ├── easy_install
│   ├── easy_install-3.6
│   ├── pip
│   ├── pip3
│   ├── pip3.6
│   ├── python -> python3
│   ├── python-config
│   ├── python3
│   ├── python3.6 -> python3
│   └── wheel
├── include
│   └── python3.6m -> /usr/include/python3.6m
└── lib
    └── python3.6

この中で、pipenv shellを実行すると上記のファイルのうちactivateが実行されます。

このactivateの中身を一部抜粋すると、

activate
()
# 仮想環境ディレクトリのPATHを環境変数にセット
VIRTUAL_ENV="/home/cuz/.local/share/virtualenvs/test-tJa6NcU0"
export VIRTUAL_ENV

# 過去の環境変数を_OLD_VIRTUAL_PATHにセット
_OLD_VIRTUAL_PATH="$PATH"

# PATHの先頭に仮想環境のPATHを設定
PATH="$VIRTUAL_ENV/bin:$PATH"
export PATH

ということをやっています。
PATHのところでは説明していませんでしたが、PATHは前から検索が行われ、最初に見つかった場所のファイルが呼ばれる仕組みになっています。

つまり、activate内では優先的に仮想環境ディレクトリのPythonやその他ライブラリを呼び出すように設定しているだけなのでした。

で?

と言われると何も言えないです。\(^o^)/
とはいえ、何も考えずにただ使ってるだけよりわかって使ってる方が、何か合った時に力になる・・・と信じたい\(^o^)/