この記事について
pyenv環境下でのPythonでmatplotlibを使おうとすると、以下のようなエラーが出る場合があります。
$ python main.py
(略)
ModuleNotFoundError: No module named '_tkinter'
「tkinterというパッケージがない」というエラーです。しかし、tkinterはPythonの標準パッケージなはず。なぜだろう?と思う方もいるでしょう。
これは、tkinterがない、というよりはtkinterの依存先であるTcl/TkというGUIツールがないことで起こっています。
(tkinterはTcl/TkのGUIをPythonで扱うためのインターフェースなので、Tcl/TkがPCに入っていないと動かないのは当然です。)
この記事では、これを解決しpyenv下でmatplotlibを使えるようにセットアップする方法を紹介します。
使用する環境・バージョン
- OS: macOS Catalina 10.15.7
- pyenv 1.2.21
- tcl-tk: stable 8.6.10 (bottled) [keg-only]
エラー解消のStep
0. (下準備)pipで入れたパッケージリストを保存しておく
これからpyenvで入れたPythonを一回抜いて再インストールする必要があります。
そのため現状復帰が楽にできるように、pipで入れたパッケージのリストを出しておきましょう。
以下のコマンドを実行します。
$ pip freeze > pip.txt
こうすることで、pip.txt
に今どのパッケージがどのバージョンで入っているのかが全て書き出されます。
1. pyenvで入れたPythonのアンインストール
pipパッケージリストの保存ができたら、一回pyenvで入れたPythonを抜きます。
# 一旦システムのPythonに切り替え
$ pyenv global system
$ pyenv versions
* system
3.X.X (set by /Users/myname/.pyenv/version)
# 3.X.Xになっていないことを確認したらアンインストール
$ pyenv uninstall 3.X.X
2. tcl-tkのインストール
tkinterインターフェースの依存先であるtcl-tkをbrewでインストールします。
$ brew install tcl-tk
(略)
==> tcl-tk
tcl-tk is keg-only, which means it was not symlinked into /usr/local,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.
If you need to have tcl-tk first in your PATH run:
echo 'export PATH="/usr/local/opt/tcl-tk/bin:$PATH"' >> /Users/myname/.bash_profile
For compilers to find tcl-tk you may need to set:
export LDFLAGS="-L/usr/local/opt/tcl-tk/lib"
export CPPFLAGS="-I/usr/local/opt/tcl-tk/include"
For pkg-config to find tcl-tk you may need to set:
export PKG_CONFIG_PATH="/usr/local/opt/tcl-tk/lib/pkgconfig"
brew install tcl-tk
を実行すると、このように「これからtcl-tkを使うためにはどのような設定を行えばいいのか」という説明書きが画面に出力されます。
なので、ここで表示された内容はどこかに書き留めておくといいでしょう。
仮にこの内容を忘れてしまって、後からこの設定を確認したいという場合は、brew info
コマンドを打てば同内容を再び見ることができます。
$ brew info tcl-tk
3. tcl-tkの設定
先ほど表示された説明書きに従って、以下の内容を.bash_profile
に追記します。
# 以下の内容を追記
export PATH="/usr/local/opt/tcl-tk/bin:$PATH"
export LDFLAGS="-L/usr/local/opt/tcl-tk/lib"
export CPPFLAGS="-I/usr/local/opt/tcl-tk/include"
export PKG_CONFIG_PATH="/usr/local/opt/tcl-tk/lib/pkgconfig"
次のコマンドで、.bash_profile
をviで開くことができるので、今の内容を書き込みましょう。
$ vi .bash_profile
4. Pythonの再インストール
tcl-tkの設定が終わったら、再びpyenvでPythonをインストールしましょう。
ただ、このpyenv install
の際に以下のようなオプションコマンドをつける必要があります。
$ PYTHON_CONFIGURE_OPTS="--with-tcltk-includes='-I/usr/local/opt/tcl-tk/include' --with-tcltk-libs='-L/usr/local/opt/tcl-tk/lib -ltcl8.6 -ltk8.6'" pyenv install 3.X.X
出典:GitHub pyenv/pyenv Issue#1375 pyenv install doesn't work with homebrew installed tcl-tk
補足: このオプションコマンドは何をしているのか
実は、このオプションなしにpyenv install 3.X.X
とだけでthinterを使おうとすると、以下のようなエラーが出ます。
RuntimeError: tk.h version (8.6) doesn't match libtk.a version (8.5)
これは、brewでインストールしたtcl-tkがversin 8.6なのに対し、pyenvが使うデフォルトのtcl-tkが8.5であることに起因しています。
そのため、あのようなオプションをつけることで、「version8.6のtcl-tkを使ってPythonをビルドするように」という設定をしているのです。
5. 動作確認
実際にエラーが解消されたかどうかを見てみましょう。
先ほどインストールしたPythonバージョンに切り替えてから確認します。
$ pyenv global 3.X.X
$ pyenv versions
system
* 3.7.4 (set by /Users/myname/.pyenv/version)
tkinterが使えるかどうか
以下のコマンドを打つことで、今使用しているPythonでthinterが使えるかどうか確認することができます。
$ python -m tkinter
無事にthinterが使えるようになっているなら、以下のようなGUIが自動で開かれるはずです。
matplotlibが使えるかどうか
tkinterが入ったことは確認できましたが、matplotlibはどうでしょうか。
まずは、matplotlib含む、pipで入れたパッケージを戻しましょう。先ほどpip.txt
にパッケージ一覧を保存しておいたので、それを元に同一パッケージ・同一バージョンのものを一気に再インストールします。
$ pip install -r pip.txt
パッケージを戻したら、実際にmatplotlibを使ったpythonコードを実行してみます。
以下のコードは、matplotlibの公式Tutorialから持ってきたものです。
#coding: utf-8
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots() # Create a figure containing a single axes.
ax.plot([1, 2, 3, 4], [1, 4, 2, 3]) # Plot some data on the axes.
plt.savefig('figure.png')