Pythonでの「ModuleNotFoundError」解決法2

内容

下の以前の記事でpipを使うことにより、モジュールをインストールすることによって、ModuleNotFoundErrorを解決する方法を書きましたが、それでも解決しない場合の対処の提案として、この記事を書きたいと思います。

参考記事:https://nayuho.hatenablog.jp/entry/2018/12/14/163948

前置き

以下のコマンドを実行して、エラー対象のモジュールをインストールしたとします。

今回はopencvのインストールを例にします。

$ pip install opencv-python

これを実行したのにも関わらず、以下のcv2をインポートしているPythonファイルが実行できなかった場合を想定します。

display.pyは標準入力から読み込ませた画像ファイルを表示させるプログラムです。

display.py 

import cv2
print("image_path?",end = " : ")
img_path = input()
img = cv2.imread(img_path)
cv2.imshow('sample', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

 実行結果

f:id:tk0137:20200920131922j:plain

pipでopencvをインストールしたのに関わらずこのようなエラーが出る場合は、パスの指定が誤っており、正しくimportできていない可能性があります。

解決方法

私がこのエラーに直面した際に試した方法とその結果を以下に示します。

まず、site-packageを呼び出した際に、cv2.cpython-38-darwin.soファイルを呼び出せるように、以下のコマンドを実行してシンボリックリンクを設定します。

パスはopencvやpythonのバージョンによって異なってくるので、以下のコマンドは参考にして実行してください。

$ ln -s /usr/local/Cellar/opencv/4.4.0_1/lib/python3.8/site-packages/cv2/python-3.8/cv2.cpython-38-darwin.so ~/.pyenv/versions/3.8.5/lib/python3.8/site-packages/

以下は実行例。

f:id:tk0137:20200921163919j:plain

上のコマンドを実行した上で再びdisplay.pyを実行します。

この時点で実行に成功するかもしれませんが、私は再び以下のような別のエラーに直面しました。

f:id:tk0137:20200921164316j:plain

これはnumpyのバージョンが古いことに起因して発生するエラーなので以下のコマンドを実行してください。

$ pip install numpy --upgrade

上のコマンドを実行した上で再びdisplay.pyを実行してみます。

この時点でも私はまだエラーが解決しなかったので、さらにパスを変更することにしました。

numpyのバージョンは新しいのにその新しいバージョンではなくて古いバージョンを参照してしまっていることに起因していると考えられます。

まず以下のようにfindコマンドを実行して、numpyがどこにあるかを確認します。

$ find / -name numpy

するとnumpyの所在が以下のように示されます。

f:id:tk0137:20200921165520j:plain

続いて、以下のようにpythonを実行して、パスを調べます。

f:id:tk0137:20200921165804j:plain

sys.pathを実行すると参照する順番にパスが表示されます。

この表示された順番にnumpyの参照先を探すと古いnumpyが参照されてしまうということですので、新たに上のものとは別のパスを追加してやる必要があります。

パスの追加には~/.bash_profileにfindコマンドで表示されていたpython3.8の下のsite-packageを選択します。

以下のコマンドを~/.bash_profileに追加します。

export PYTHONPATH="/usr/local/lib/python3.8/site-packages/"

参考までに。

私は最後の行に追加しています。

f:id:tk0137:20200921170624p:plain

この~/.bash_profileの設定を反映するために以下のコマンドを実行します。

$ source ~/.bash_profile

ここまでの作業を行っても一度実行します。

三度目の正直。

 実行結果

f:id:tk0137:20200921171142j:plain

エラーが出ず、無事に標準入力を求める文字列が表示されました。

最後に

私もこのエラーにはかなり頭を悩まされたので、お役に立てることができれば幸いです。

ありがとうございました。