linuxBean14.04(44)Pythonモジュールのインポートエラーに悩まされる

ラベル: ,

前の関連記事:linuxBean14.04(43)動かないpipを再インストール


psutilをアップグレードしたら動かなくなって四苦八苦しました。結論としてはlinuxBean14.04(38)LibreOfficeバンドルPythonにパッケージを追加で作成したsites.pthファイルのパスの順番を書き換えてしまったのが原因でした。単純ミスが原因でした。

Pythonモジュールを検索するパスの順序は重要

pq@pq-VirtualBox:~$ python3.3 /usr/lib/python3.3/site.py
sys.path = [
    '/usr/lib/python3.3',
    '/usr/lib/python3.3/plat-i386-linux-gnu',
    '/usr/lib/python3.3/lib-dynload',
    '/home/pq/.local/lib/python3.3/site-packages',
    '/usr/local/lib/python3.3/dist-packages',
    '/usr/lib/python3/dist-packages',
]
USER_BASE: '/home/pq/.local' (exists)
USER_SITE: '/home/pq/.local/lib/python3.3/site-packages' (exists)
ENABLE_USER_SITE: True
site.pyで確認したpython3.3のデフォルトパス設定です。

sys.pathに書いてある順番にモジュールを探していき、最初に見つかったモジュールをインポートする仕組みになっているようです。

linuxBeanではSynapticパッケージマネージャでインストールしたPythonパッケージ(モジュールの集合をパッケージという)のモジュールは/usr/lib/python3/dist-packagesにインストールされて、python3.3でもpython3.4でも使えます。

python3.3のpip、つまりpip3.3でパッケージをインストールすると/usr/local/lib/python3.3/dist-packagesにインストールされます。

pip3.3 install パッケージ名 --user というように--userオプションをつけると~/.local/lib/python3.3/site-packagesにインストールされます。

ユーザー領域にインストールされるのでsudoとしなくてもインストールされます。

pip3.3を使ってインストールするこれら2つの方法はPython3.4からは使えずPython3.3でのみ使えます。

~/.local/lib/python3.3/site-packages
/usr/local/lib/python3.3/dist-packages
/usr/lib/python3/dist-packages

site.pyの結果をみると、sys.pathに追加されるパスの順序はこのようになっています。

pip3.3 install パッケージ名 --user
sudo -H pip3.3 install パッケージ名
Synapticパッケージマネージャ

インストール方法で表現するとこの順序になります。

とくに最後のSynapticeパッケージマネージャでインストールされたものはpipでアップグレードしても古いバージョンのファイルは削除されずにそのまま残っています。

なので、Pythonモジュールの検索パスの順序に/usr/lib/python3/dist-packagesが最後でない場合はパッケージはインストールされているのにインポートエラーがでるといった症状に悩まされることになります。

pthファイルのパスの順序はデフォルトのパスの順序を上書きしてしまう


linuxBean14.04(38)LibreOfficeバンドルPythonにパッケージを追加で作ったsites.pthファイルはsys.pathの出力結果を、そのままの順序で作成しないといけません。

/usr/lib/python3.3
/usr/lib/python3.3/plat-i386-linux-gnu
/usr/lib/python3.3/lib-dynload
/usr/local/lib/python3.3/dist-packages
/usr/lib/python3/dist-packages

ところがこれを間違えて最後の2つの順序を入れ替えてしまったsites.pthファイルを~/.local/lib/python3.3/site-packagesに置いてみましょう。
pq@pq-VirtualBox:~$ python3.3 /usr/lib/python3.3/site.py
sys.path = [
    '/usr/lib/python3.3',
    '/usr/lib/python3.3/plat-i386-linux-gnu',
    '/usr/lib/python3.3/lib-dynload',
    '/home/pq/.local/lib/python3.3/site-packages',
    '/usr/lib/python3/dist-packages',
    '/usr/local/lib/python3.3/dist-packages',
]
USER_BASE: '/home/pq/.local' (exists)
USER_SITE: '/home/pq/.local/lib/python3.3/site-packages' (exists)
ENABLE_USER_SITE: True
site.pyで確認してみるとsite.pthファイルの内容が優先されてデフォルトの順番が入れ替わっています。

この状態でもsudo -H pip3.3 install パッケージ名 -Uでパッケージのアップグレードができます。

しかしアップグレード元のパッケージがSynapticパッケージマネージャでインストールされたもの(つまりUbuntuパッケージのPythonパッケージ)である場合、/usr/lib/python3/dist-packages
にパッケージファイルが残ったままです。

そのためアップグレードしたモジュールをimportしようとしてもエラーが出ます。(ただしpsutilの場合しか確認していません。)

モジュールのインストールがうまく行っていないのかと思ってパッケージのインストールをしようとすると、そのパッケージはすでにインストール済だと言われます。

困ってしまってSynapticパッケージマネージャからpython3-psutilをアンインストールするとpipでアップグレードしたpstuilがインポートできるようになりました。

ところがpython3-psutilはlinuxBeanのメニューエディターのlibremenuで使われており、python3-psutilをアンインストールしてしまうとlibremenuもアンインストールされてしまいます。

ほかのlinuxBeanを同じように設定しているマシンではこのような問題は起こっておらず、原因を探した結果、ようやくsites.pthによるモジュールの検索パスの順序の変化に気がついたのでした。

sites.pthはLibreOfficeのバンドルPythonにしか影響がないと思い込んでいたのでPython3.3の原因として思いつくまで時間がかかってしまいました。

参考にしたサイト


pipの使い方 (2014/1バージョン) — そこはかとなく書くよん。
pipのいろいろな使い方が解説されています。

次の関連記事:linuxBean14.04(45)LibreOfficeのバンドルPythonでコールグラフ

PR

0 件のコメント:

コメントを投稿