はじめに
TkinterはPythonでGUIを組むことのできるツールキットです。これを使用してツールを作ろうとしたところ、MacではNSInvalidArgumentExceptionエラーが出て、動作しませんでした。これはbackendの指定に問題があったようです。
backend
matplotlibをPythonシェルからインタラクティブに使用する人もいれば、Jupyterのノートブックを実行し、インラインプロットを描く人もいます。豊富なアプリケーションを構築するために、wxpythonやpygtkのようなグラフィカルユーザインタフェースにmatplotlibを組み込む人もいます。matplotlibはこれらの様々な出力先に対応できるようになっており、その設定がbackendと呼ばれます。今回はTkinter用のbackendを指定する必要がありました。
参考
- Weird interaction with Tkinter #10239 > matplotlibのbackendの設定
- OS X 10.6.8 - Tkinter crashing _GUI scripts #29 > matplotlibのbackendの設定
- Usage Guide > backendに関する解説
- Crash on Mac OS when importing Tkinter #110 > MacOS特有の問題に関する解決策
環境
- macOS Mojave 10.14.2
- python 3.6.7
手順
エラーが起きるとターミナルに次のようなメッセージが出力されます。
2018-12-18 00:22:20.180 python[37108:1011614] -[NSApplication _setup:]: unrecognized selector sent to instance 0x7ff8acdfaa40
2018-12-18 00:22:20.183 python[37108:1011614] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSApplication _setup:]: unrecognized selector sent to instance 0x7ff8acdfaa40'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff4c4f5ecd __exceptionPreprocess + 256
1 libobjc.A.dylib 0x00007fff785ad720 objc_exception_throw + 48
2 CoreFoundation 0x00007fff4c573275 -[NSObject(NSObject) __retain_OA] + 0
3 CoreFoundation 0x00007fff4c497b40 ___forwarding___ + 1486
4 CoreFoundation 0x00007fff4c4974e8 _CF_forwarding_prep_0 + 120
5 libtk8.6.dylib 0x0000001c17e6c31d TkpInit + 413
6 libtk8.6.dylib 0x0000001c17dc417e Initialize + 2622
7 _tkinter.cpython-36m-darwin.so 0x0000001c14fe8a16 _tkinter_create + 1174
8 python 0x0000000100cec088 _PyCFunction_FastCallDict + 200
9 python 0x0000000100dc2f4f call_function + 143
10 python 0x0000000100dc0abf _PyEval_EvalFrameDefault + 46847
11 python 0x0000000100db4209 _PyEval_EvalCodeWithName + 425
12 python 0x0000000100dc3b1c _PyFunction_FastCallDict + 364
13 python 0x0000000100c6a8b0 _PyObject_FastCallDict + 320
14 python 0x0000000100c91fe8 method_call + 136
15 python 0x0000000100c71efe PyObject_Call + 62
16 python 0x0000000100d13385 slot_tp_init + 117
17 python 0x0000000100d178c1 type_call + 241
18 python 0x0000000100c6a821 _PyObject_FastCallDict + 177
19 python 0x0000000100dc3048 call_function + 392
20 python 0x0000000100dc0abf _PyEval_EvalFrameDefault + 46847
21 python 0x0000000100db4209 _PyEval_EvalCodeWithName + 425
22 python 0x0000000100daea79 builtin_exec + 345
23 python 0x0000000100cec088 _PyCFunction_FastCallDict + 200
24 python 0x0000000100dc2f4f call_function + 143
25 python 0x0000000100dc0abf _PyEval_EvalFrameDefault + 46847
26 python 0x0000000100db4209 _PyEval_EvalCodeWithName + 425
27 python 0x0000000100dc33ba fast_function + 362
28 python 0x0000000100dc2fac call_function + 236
29 python 0x0000000100dc0abf _PyEval_EvalFrameDefault + 46847
30 python 0x0000000100dc330c fast_function + 188
31 python 0x0000000100dc2fac call_function + 236
32 python 0x0000000100dc0abf _PyEval_EvalFrameDefault + 46847
33 python 0x0000000100db4209 _PyEval_EvalCodeWithName + 425
34 python 0x0000000100dc33ba fast_function + 362
35 python 0x0000000100dc2fac call_function + 236
36 python 0x0000000100dc0abf _PyEval_EvalFrameDefault + 46847
37 python 0x0000000100dc330c fast_function + 188
38 python 0x0000000100dc2fac call_function + 236
39 python 0x0000000100dc0abf _PyEval_EvalFrameDefault + 46847
40 python 0x0000000100db4209 _PyEval_EvalCodeWithName + 425
41 python 0x0000000100cb55bd function_call + 125
42 python 0x0000000100c71efe PyObject_Call + 62
43 python 0x0000000100dc0cc0 _PyEval_EvalFrameDefault + 47360
44 python 0x0000000100db4209 _PyEval_EvalCodeWithName + 425
45 python 0x0000000100cb55bd function_call + 125
46 python 0x0000000100c71efe PyObject_Call + 62
47 python 0x0000000100dc0cc0 _PyEval_EvalFrameDefault + 47360
48 python 0x0000000100db4209 _PyEval_EvalCodeWithName + 425
49 python 0x0000000100cb55bd function_call + 125
50 python 0x0000000100c71efe PyObject_Call + 62
51 python 0x0000000100dc0cc0 _PyEval_EvalFrameDefault + 47360
52 python 0x0000000100db4209 _PyEval_EvalCodeWithName + 425
53 python 0x0000000100dc33ba fast_function + 362
54 python 0x0000000100dc2fac call_function + 236
55 python 0x0000000100dc0b6f _PyEval_EvalFrameDefault + 47023
56 python 0x0000000100db4209 _PyEval_EvalCodeWithName + 425
57 python 0x0000000100dc33ba fast_function + 362
58 python 0x0000000100dc2fac call_function + 236
59 python 0x0000000100dc0abf _PyEval_EvalFrameDefault + 46847
60 python 0x0000000100db4209 _PyEval_EvalCodeWithName + 425
61 python 0x0000000100e0cd4c PyRun_FileExFlags + 252
62 python 0x0000000100e0c224 PyRun_SimpleFileExFlags + 372
63 python 0x0000000100e32d66 Py_Main + 3734
64 python 0x0000000100c62929 main + 313
65 libdyld.dylib 0x00007fff7967bed9 start + 1
66 ??? 0x0000000000000009 0x0 + 9
)
libc++abi.dylib: terminating wi
これを解決するにはスクリプトの最初にbackendの設定を記述します。
import matplotlib
matplotlib.use('tkagg')
ここで、サイトによっては引数を'TkAgg'
としている場合があります。精査していませんが、python2.7の場合は'TkAgg'
と思われます。私の環境(python 3.6.7)では'tkagg'
で動作しました。
おわりに
'TkAgg'
と書いたばかりに3時間ほど浪費しました。
ちなみに他にもいくつかbackendがあります。
Backend | Description |
---|---|
Qt5Agg | Agg rendering in a Qt5 canvas (requires PyQt5). This backend can be activated in IPython with %matplotlib qt5. |
ipympl | Agg rendering embedded in a Jupyter widget. (requires ipympl). This backend can be enabled in a Jupyter notebook with %matplotlib ipympl. |
GTK3Agg | Agg rendering to a GTK 3.x canvas (requires PyGObject, and pycairo or cairocffi). This backend can be activated in IPython with %matplotlib gtk3. |
macosx | Agg rendering into a Cocoa canvas in OSX. This backend can be activated in IPython with %matplotlib osx. |
TkAgg | Agg rendering to a Tk canvas (requires TkInter). This backend can be activated in IPython with %matplotlib tk. |
nbAgg | Embed an interactive figure in a Jupyter classic notebook. This backend can be enabled in Jupyter notebooks via %matplotlib notebook. |
WebAgg | On show() will start a tornado server with an interactive figure. |
GTK3Cairo | Cairo rendering to a GTK 3.x canvas (requires PyGObject, and pycairo or cairocffi). |
Qt4Agg | Agg rendering to a Qt4 canvas (requires PyQt4 or pyside). This backend can be activated in IPython with %matplotlib qt4. |
WXAgg | Agg rendering to a wxWidgets canvas (requires wxPython 4). This backend can be activated in IPython with %matplotlib wx. |
動かないときはすべて小文字にして試してみるとよいのかもしれません。
また、Macの場合はTcl/Tkにバグが有る場合があり、環境を再構築する必要がある場合もあります。