環境
date 2018/10/18
Ubuntu 16.04
Anaconda
conda 4.5.11
python 3.6.5
pip 18.0
現象
あるとき、pythonのスクリプトが急にSegmentation faultするようになりました。
特にスタックトレースも表示されず、原因特定は面倒でしたが、
どうもimport行で起こると気づいてからは、exit()を適当に差し込んで問題のあるモジュールを特定しました。
結果、
from matplotlib import pyplot as plt
が容疑行として浮上しました。
対話コンソールでも再現しました。
$ python
Python 3.6.5 |Anaconda, Inc.| (default, Apr 29 2018, 16:14:56)
[GCC 7.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from matplotlib import pyplot
[1] 18382 segmentation fault (core dumped) python
結論
conda install -c conda-forge opencv
でmatplotlib(というかpyplot)が使えなくなったとき、
ソースコードの修正で対応する場合
https://github.com/matplotlib/matplotlib/issues/9294
を参考に、
import matplotlib as mpl
mpl.use('TkAgg')
import matplotlib.pyplot as plt
とりあえずこれで回避はできました。
パッケージを入れなおす場合
ただ場合によってはソースコード編集ができない・やりたくないケースもあるだろうと思いますので、そのときは、
conda install qt
conda remove opencv
pip install opencv-python
と、Qtのバージョンを最新にしつつopencvをcondaからpipに変更します。
経緯
冒頭の現象が起こる直前、ChainerとcupyとOpenCVをインストールしていました。
どうも怪しそうなのはOpenCVです。OpenCVをインストールしたときの怪しそうなものをピックアップしました。
$ conda install -c conda-forge opencv
Solving environment: done
(中略)
The following packages will be downloaded:
package | build
---------------------------|-----------------
cairo-1.14.12 | he56eebe_3 1.3 MB conda-forge
(中略)
matplotlib-2.2.2 | py36_1 9.2 MB conda-forge
------------------------------------------------------------
Total: 296.5 MB
The following NEW packages will be INSTALLED:
(中略)
The following packages will be UPDATED:
(中略)
matplotlib: 2.2.2-py36h0e671d2_1 --> 2.2.2-py36_1 conda-forge
numexpr: 2.6.5-py36h7bf3b9c_0 --> 2.6.6-py36h470a237_1 conda-forge
numpy: 1.14.3-py36hcd700cb_1 --> 1.15.2-py36_blas_openblashd3ea46f_1 conda-forge [blas_openblas]
numpy-base: 1.14.3-py36h9be14a7_1 --> 1.14.3-py36h0ea5e3f_1
openssl: 1.0.2o-0 conda-forge --> 1.0.2p-h470a237_1 conda-forge
scikit-learn: 0.19.1-py36h7aa7ec6_0 --> 0.19.1-py36_blas_openblas_201 conda-forge [blas_openblas]
scipy: 1.1.0-py36hfc37229_0 --> 1.1.0-py36_blas_openblash7943236_201 conda-forge [blas_openblas]
The following packages will be DOWNGRADED:
(中略)
pyqt: 5.9.2-py36h751905a_0 --> 5.6.0-py36_2
qt: 5.9.5-h7e424d6_0 --> 5.6.2-h974d657_12
Qtのバージョンを戻してみます。
$ conda install qt
Solving environment: done
(中略)
The following packages will be downloaded:
package | build
---------------------------|-----------------
conda-4.5.11 | py36_0 1.0 MB
openssl-1.0.2p | h14c3975_0 3.5 MB
libopencv-3.4.1 | h1a3b859_1 41.5 MB
opencv-3.4.1 | py36h6fd60c2_2 7 KB
certifi-2018.10.15 | py36_0 139 KB
py-opencv-3.4.1 | py36h0676e08_1 1.2 MB
------------------------------------------------------------
Total: 47.3 MB
The following NEW packages will be INSTALLED:
libopencv: 3.4.1-h1a3b859_1
py-opencv: 3.4.1-py36h0676e08_1
The following packages will be UPDATED:
dbus: 1.13.0-h3a4f0e9_0 conda-forge --> 1.13.2-h714fa37_1
glib: 2.55.0-h464dc38_2 conda-forge --> 2.56.1-h000015b_0
gst-plugins-base: 1.12.5-hde13a9d_0 conda-forge --> 1.14.0-hbbd80ab_1
gstreamer: 1.12.5-h61a6719_0 conda-forge --> 1.14.0-hb453b48_1
matplotlib: 2.2.2-py36_1 conda-forge --> 2.2.2-py36h0e671d2_1
numpy-base: 1.14.3-py36h0ea5e3f_1 --> 1.14.3-py36h9be14a7_1
pyqt: 5.6.0-py36_2 --> 5.9.2-py36h751905a_0
qt: 5.6.2-h974d657_12 --> 5.9.5-h7e424d6_0
The following packages will be DOWNGRADED:
blas: 1.1-openblas conda-forge --> 1.0-mkl
ca-certificates: 2018.10.15-ha4d7672_0 conda-forge --> 2018.03.07-0
cairo: 1.14.12-he56eebe_3 conda-forge --> 1.14.12-h7636065_2
certifi: 2018.10.15-py36_1000 conda-forge --> 2018.10.15-py36_0
conda: 4.5.11-py36_1000 conda-forge --> 4.5.11-py36_0
harfbuzz: 1.8.5-h2bb21d5_0 conda-forge --> 1.7.6-h5f0a787_1
numpy: 1.15.2-py36_blas_openblashd3ea46f_1 conda-forge [blas_openblas] --> 1.14.3-py36hcd700cb_1
opencv: 3.4.3-py36_blas_openblash829a850_200 conda-forge [blas_openblas] --> 3.4.1-py36h6fd60c2_2
openssl: 1.0.2p-h470a237_1 conda-forge --> 1.0.2p-h14c3975_0
scikit-learn: 0.19.1-py36_blas_openblas_201 conda-forge [blas_openblas] --> 0.19.1-py36h7aa7ec6_0
scipy: 1.1.0-py36_blas_openblash7943236_201 conda-forge [blas_openblas] --> 1.1.0-py36hfc37229_0
すると、matplotlibはエラーがなくなりましたが、今度はOpenCVが死にます。
$ python using_opencv_script.py
Traceback (most recent call last):
File "cupy_grid_automaton.py", line 7, in <module>
import cv2
ImportError: /home/(censored)/anaconda3/lib/python3.6/site-packages/../../libopencv_dnn.so.3.4: undefined symbol: _ZNK6google8protobuf7Message25InitializationErrorStringB5cxx11Ev
の最初のアドバイス通り、モジュールを一部変更します。
% conda install -c defaults libprotobuf protobuf
Solving environment: done
(中略)
protobuf: 3.5.2-py36_0 conda-forge --> 3.5.2-py36hf484d3e_1
libprotobuf: 3.5.2-hd28b015_1 conda-forge --> 3.5.2-h6f1eeef_0
エラーが変わりました。
Traceback (most recent call last):
File "cupy_grid_automaton.py", line 78, in <module>
main()
File "cupy_grid_automaton.py", line 67, in main
cv2.imshow("test", img)
cv2.error: OpenCV(3.4.1) /opt/conda/conda-bld/opencv-suite_1527005194613/work/modules/highgui/src/window.cpp:636: error: (-2) The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Carbon support. If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script in function cvShowImage
を見ていると、そもそもcondaのopencvは良くないのではと思い至り、
を参考に、
$ conda remove opencv
$ pip install opencv-python
としました。なお、一通りローカルで管理したいと思っているので、pipでもsudoはしませんでした。
これで改めてmatplotlibとOpenCVを両方試すと、ともに無事実行できました。
予想ですが、condaにおいて、OpenCVが対応するQtのバージョンと、matplotlibが対応するQtのバージョンが一致しないのが原因ではないかなと。
その他
こういう試行錯誤を仮想環境とかでなく直にするからそのうちどうしようもなくなる。
ちなみに、OpenCVはcondaのものよりpyPI提供のものの方が結構実行速度が速いように感じました。