Pythonの仮想環境にモジュールをインストールしたのに、システム側からもそのモジュールが認識出来てしまったのは何故か?という話

まずはPygameをインストールしようと思ったところから

ことの起こりはPygameをインストールしようとしたところから。
システムと開発環境を分けるためにvenvで仮想環境を作って、そこにPygameを入れようと以下のページは参考に操作していました。
GettingStarted - pygame wiki
そこに書かれていたコマンドは
$ python3 -m pip install -U pygame --user
これでインストール自体はちゃんと出来ました。がしかし、Pythonのインタープリタから
>>> import pygame
としてもエラーが出てしまい読み込むことが出来ません。インストール時のpipのオプションに付けた--userが余計だったのか?と思い、このオプションを付けずに再度インストールコマンドを実行。今度は、ちゃんとimportでpygameを読み込めるようになりました。

と、話がここで終わっていればよかったのですが、初めに--userオプションを付けて実行したことが尾を引いて影響してきます…。

何がどうなったのか?

今回は仮想環境(venv)のPythonにPygameをインストールしました。仮想環境ですから当然このPygameは仮想領域に分離されていてシステム側のPythonからは認識出来ないはずです。が、しかし試しにシステム側のPythonでimportしてみるとPygameを読み込むことが出来てしまいました…。
はてさてこれはどういうことなのだろう?と思い、aptでシステム側にPygameをインストールしていないかを調べましたがそんなことは無し。じゃあシステム側のPythonのpipでインストールしたのではと思ったのですが、システム側にはpipはインストールしていないのでそもそもそんなこともあり得ません。
この時点で考えられることとしては、実は仮想環境でインストールしたのはシステム側からも認識出来ちゃいますというパターン。ですが、それじゃ何のための仮想環境なんだか分かったもんじゃありません。とりあえず、その線はかなり可能性が低いだろうと判断して他の原因を探ることにしました。

まずPygameが一体どこにインストールされているのかlocateコマンドで探してみます。
$ locate pygame

pygameのディレクトリが存在したのは仮想環境下のディレクトリ。そこにあるのは当然でしょう。そしてここでもう一つpygameのディレクトリがホームディレクトリ下の「~/.local」ディレクトリ以下にも存在していることが分かりました。おそらくシステム側のPythonのPathがここに通っているために、pygameが読み込めてしまっているのだろうと判断しました。案の定、ここのpygameのディレクトリを適当な場所に退避させると、システム側からは読み込めないようになりました。

で、なんでこんな場所にPygameがインストールされてしまっているのかを考えると、ここで一番初めに実行したインストールコマンドに行き着きます。あの時、pipに--userオプションを付けて実行したがために、仮想環境下ではなく、ユーザー環境下の.localにインストールされてしまったということ。初めにインストールは成功したのに仮想環境からはPygameが読み込めなかったのもそのためでしょう。

話はだいたい片が付いたので、.local以下のPygameはアンインストールしてあるべき状態に戻すことにします。ちなみに仮想環境でpipからは.local以下にインストールされたものはアンインストール出来ないようです。pipのuninstallでは--userオプションもありません。インストールは出来たのになんでアンインストールは出来ないのかな?と疑問なのですが、こんなことに余計に時間を取られてもしょうがないので、手動で削除することにしました。

最後に

以上によりシステム側のPythonからはPygameは読み込めず、仮想環境では読み込めるという、「こうなって欲しかった」という状態に持ってくることが出来ました。
さてさて話の種が分かればなんてことはない結果でしたが、 そもそも仮想環境やpipによるインストールの仕組みをよく把握していないとなかなかにしてハマってしまう話ではないでしょうか。ちゃんと勉強しながら覚えていかないとダメですね、はい。がんばります。


コメント

スポンサーリンク


このブログの人気の投稿

Ubuntu Softwareが起動しないのでいろいろと調べてみる(Ubuntu 20.04.1 LTS)

gnuplotでプロットなどの色をcolornameの指定で変更する

gnuplot : グラフにグリッド線を描く方法(set grid)

gnuplot : プロット画像のサイズ指定について(set sizeとの違い)

Pythonのformat()を使って1桁の16進数でも2桁で出力する方法