Environment

System: MacOS catalina 10.15

Python Version: 3.7.4/3.8.0

Error message:

1
2
3
import _tkinter # If this fails your Python may not be configured for Tk 

ImportError: No module named _tkinter

問題描述

筆者使用pyenv架設python環境,在import tkinter出現了錯誤:

1
ImportError: No module named _tkinter

這是由於pyenv在安裝python時沒有將適當的環境變數引入,或是沒有安裝tcl-tk

問題解決

(不想看這麼多的話可以直接跳到**懶人包**)

先確認有沒有安裝tcl-tk,沒有的話按照下列方式安裝。

1
2
3
# 引入tck-tk
brew update
brew install tcl-tk

使用brew內建的python的話,僅需要移除原本的python再加入flag安裝就好了。

1
2
3
brew uninstall python3
brew install python3 --with-tcl-tk
# 不需要進行下一步

安裝完之後,在~/.bashrc或是~/.zshrc等初始設定檔中加入以下環境變數:

1
2
3
4
5
# tcl-tk solution
TKPATH="/usr/local/opt/tcl-tk"
export LDFLAGS="-L$TKPATH/lib"
export CPPFLAGS="-I$TKPATH/include"
export PATH=$PATH:$TKPATH/bin

不過因為LDFLAGSCPPFLAGS很常用到(可能有些其他程式也需要),所以沒必要的話可以用別的方式替代,後面會有code可以直接解決。

記得要重新啟動shell,或是直接輸入exec $SHELL

移除原本的python,再重新安裝。

1
2
3
4
5
6
7
8
9
#備份pip
pip freeze > requirements.txt

pyenv uninstall 3.8.0
pyenv install 3.8.0
pyenv global 3.8.0

#還原pip
pip install -r requirements.txt

最後執行測試code

1
python -m tkinter

出現了RuntimeError

1
RuntimeError: tk.h version (8.6) doesn't match libtk.a version (8.5)

這是因為環境變數PYTHON_CONFIGURE_OPTS沒有指定tk版本,因此再加入環境變數:

1
export PYTHON_CONFIGURE_OPTS="--with-tcltk-libs='$LDFLAGS -ltcl8.6 -ltk8.6' --with-tcltk-includes=$CPPFLAGS"

最後一樣重新安裝就可以了。

懶人code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# brew 設定環境
brew update
brew uninstall python3
brew install tcl-tk
brew install pyenv
brew install python3 --with-tcl-tk

# 設定tk path
TKPATH=$(brew --prefix tcl-tk)
LDFLAGS="-L$TKPATH/lib"
CPPFLAGS="-I$TKPATH/include"
PYTHON_CONFIGURE_OPTS="--with-tcltk-libs='$LDFLAGS -ltcl8.6 -ltk8.6' --with-tcltk-includes=$CPPFLAGS"

# zsh使用者
echo "export PYTHON_CONFIGURE_OPTS=\"$PYTHON_CONFIGURE_OPTS\"" >> ~/.zshrc

# bashsh使用者
echo "export PYTHON_CONFIGURE_OPTS=\"$PYTHON_CONFIGURE_OPTS\"" >> ~/.bashrc

# Check successful
version="3.8.0"
pyenv install $version
pyenv global $version
python -m tkinter

或是你想要直接進到設定檔,直接加入這行:

1
2
# 注意tk位置可能會不同,請先確認
export PYTHON_CONFIGURE_OPTS="--with-tcltk-libs='-L/usr/local/opt/tcl-tk/lib -ltcl8.6 -ltk8.6' --with-tcltk-includes=-I/usr/local/opt/tcl-tk/include"

原理

pyenv在安裝python的時候會偵測環境變數PYTHON_CONFIGURE_OPTS--with-tcltk-libs以及--with-tcltk-includes。因此在環境變數中設定PYTHON_CONFIGURE_OPTS就能解決問題。


Reference

  1. https://yopiyama.hatenablog.com/entry/2019/09/02/052513
  2. https://stackoverflow.com/questions/22550068/python-not-configured-for-tk/31299142#31299142
  3. https://github.com/jiansoung/issues-list/issues/15
  4. https://github.com/pyenv/pyenv/pull/1397