Unable to install tkinter with pyenv Pythons on MacOS

16,123

Solution 1

TL;DR set the env. vars. mentioned in tcl-tk's caveats and this GitHub comment when installing new Pythons via pyenv to get tkinter.

First, ensure you have the latest tcl-tk via homebrew and then pay attention to its caveats:

※ brew install tcl-tk
※ brew info tcl-tk
tcl-tk: stable 8.6.10 (bottled) [keg-only]
...
==> Caveats
tcl-tk is keg-only, which means it was not symlinked into /usr/local,
because tk installs some X11 headers and macOS provides an (older) Tcl/Tk.

If you need to have tcl-tk first in your PATH run:
  echo 'export PATH="/usr/local/opt/tcl-tk/bin:$PATH"' >> ~/.zshrc

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"
...

You'll also need to know about pyenv's PYTHON_CONFIGURE_OPTS, --with-tcltk-includes, and --with-tcltk-libs, e.g. from this comment.

Next, reinstall Python with the environment variables active:

※ pyenv uninstall 3.8.1
※ env \
  PATH="$(brew --prefix tcl-tk)/bin:$PATH" \
  LDFLAGS="-L$(brew --prefix tcl-tk)/lib" \
  CPPFLAGS="-I$(brew --prefix tcl-tk)/include" \
  PKG_CONFIG_PATH="$(brew --prefix tcl-tk)/lib/pkgconfig" \
  CFLAGS="-I$(brew --prefix tcl-tk)/include" \
  PYTHON_CONFIGURE_OPTS="--with-tcltk-includes='-I$(brew --prefix tcl-tk)/include' --with-tcltk-libs='-L$(brew --prefix tcl-tk)/lib -ltcl8.6 -ltk8.6'" \
  pyenv install 3.8.1

It should work now:

※ pyenv global 3.8.1
※ python
Python 3.8.1 (default, Feb 29 2020, 11:56:10)
[Clang 11.0.0 (clang-1100.0.33.17)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import tkinter
>>> tkinter.TclVersion, tkinter.TkVersion
(8.6, 8.6)
>>> tkinter._test()
# You should get a GUI

If you get the following error, you might be missing the PYTHON_CONFIGURE_OPTS env. var. above.

DEPRECATION WARNING: The system version of Tk is deprecated and may be removed in a future release. Please don't rely on it. Set TK_SILENCE_DEPRECATION=1 to suppress this warning.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/factor/.pyenv/versions/3.8.1/lib/python3.8/tkinter/__init__.py", line 4552, in _test
    root = Tk()
  File "/Users/factor/.pyenv/versions/3.8.1/lib/python3.8/tkinter/__init__.py", line 2263, in __init__
    self._loadtk()
  File "/Users/factor/.pyenv/versions/3.8.1/lib/python3.8/tkinter/__init__.py", line 2279, in _loadtk
    raise RuntimeError("tk.h version (%s) doesn't match libtk.a version (%s)"
RuntimeError: tk.h version (8.6) doesn't match libtk.a version (8.5)

Solution 2

Here is step by step guide to make tkinter (and IDLE) work if you use pyenv for Python environments management on macOS:

  1. install tcl-tk with Homebrew. In shell run brew install tcl-tk
  2. in shell run echo 'export PATH="/usr/local/opt/tcl-tk/bin:$PATH"' >> ~/.zshrc
  3. reload shell by quitting Terminal app or run source ~/.zshrc
  4. after reloaded check that tck-tk is in $PATH. Run echo $PATH | grep --color=auto tcl-tk. As the result you should see your $PATH contents with tcl-tk highlighted
  5. now we run three commands from Homebrew's output from step #1
    1. in shell run export LDFLAGS="-L/usr/local/opt/tcl-tk/lib"
    2. in shell run export CPPFLAGS="-I/usr/local/opt/tcl-tk/include"
    3. in shell run export PKG_CONFIG_PATH="/usr/local/opt/tcl-tk/lib/pkgconfig"
  6. if you have your Python version already installed with pyenv then uninstall it with pyenv uninstall <your python version>. E.g. pyenv uninstall 3.8.2
  7. set environment variable that will be used by python-build. In shell run 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'" Note: in future use tck-tk version that actually installed with Homebrew. At the moment of posting 8.6 was the actual
  8. finally install Python with pyenv with pyenv install <version>. E.g. pyenv install 3.8.2

Test

  1. in shell run pyenv global <verion that you've just installed>
  2. now check IDLE. In shell run idle. You should see IDLE window without any warnings and "text printed in red".

IDLE window run from Terminal. No warnings

  1. now check tkinter. In shell run python -m tkinter -c "tkinter._test()". You should see test window like on the image:

tkinter test window

That's it!

My environment:

check this is something went wrong executing steps above:

  1. macOS Catalina
  2. zsh (included in macOS Catalina) = "shell" above
  3. Homebrew (installed with instructions from Homebrew official website)
  4. pyenv (installed with Homebrew and PATH updated according to pyenv official readme from GitHub)
  5. Python 3.8.x - 3.9.x (installed with pyenv install <version> command)

Solution 3

For MacOS Big Sur (11.2.3), Carl G's answer didn't work for me because I got a zlib error. Building off of this answer and this blog post, I found success with

brew install bzip2
export LDFLAGS="-L $(xcrun --show-sdk-path)/usr/lib -L brew --prefix bzip2/lib"
export CFLAGS="-L $(xcrun --show-sdk-path)/usr/include -L brew --prefix bzip2/include"
export 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' --enable-framework"
pyenv install 3.8.6
Share:
16,123

Related videos on Youtube

Carl G
Author by

Carl G

Full-stack developer. Currently working in big data analytics. #SOreadytohelp

Updated on June 27, 2022

Comments

  • Carl G
    Carl G almost 2 years

    Versions of Python installed via pyenv fail to import tkinter:

    ※ python
    Python 3.8.1 (default, Feb 29 2020, 11:45:59)
    [Clang 11.0.0 (clang-1100.0.33.17)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import tkinter
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/Users/factor/.pyenv/versions/3.8.1/lib/python3.8/tkinter/__init__.py", line 36, in <module>
        import _tkinter # If this fails your Python may not be configured for Tk
    ModuleNotFoundError: No module named '_tkinter'
    >>>
    

    or you might get a message about the header version doesn't match the binary:

    DEPRECATION WARNING: The system version of Tk is deprecated and may be removed in a future release. Please don't rely on it. Set TK_SILENCE_DEPRECATION=1 to suppress this warning.
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/Users/factor/.pyenv/versions/3.8.1/lib/python3.8/tkinter/__init__.py", line 4552, in _test
        root = Tk()
      File "/Users/factor/.pyenv/versions/3.8.1/lib/python3.8/tkinter/__init__.py", line 2263, in __init__
        self._loadtk()
      File "/Users/factor/.pyenv/versions/3.8.1/lib/python3.8/tkinter/__init__.py", line 2279, in _loadtk
        raise RuntimeError("tk.h version (%s) doesn't match libtk.a version (%s)"
    RuntimeError: tk.h version (8.6) doesn't match libtk.a version (8.5)
    
  • davedgd
    davedgd over 3 years
    This was very helpful! I was able to do it in fewer steps by simply using the env approach (i.e., no need to edit ~/.zshrc to add all the exports): env PYTHON_CONFIGURE_OPTS="--with-tcltk-includes='-I/usr/local/o‌​pt/tcl-tk/include' --with-tcltk-libs='-L/usr/local/opt/tcl-tk/lib -ltcl8.6 -ltk8.6' --enable-shared" pyenv install 3.8.5 I added --enable-shared since PyInstaller needs it. If you don't need it: env PYTHON_CONFIGURE_OPTS="--with-tcltk-includes='-I/usr/local/o‌​pt/tcl-tk/include' --with-tcltk-libs='-L/usr/local/opt/tcl-tk/lib -ltcl8.6 -ltk8.6'" pyenv install 3.8.5
  • Lane Rettig
    Lane Rettig over 3 years
    For the record this worked out-of-the-box on Linux (Debian 10) as well. The only difference is that the output of brew info was a bit different.
  • CodingNow
    CodingNow over 3 years
    Thanks. This saved my life.
  • BergP
    BergP over 3 years
    after I did this, I cannot install python anymore, it shows: BUILD FAILED (OS X 11.1 using python-build 20180424)
  • Carl G
    Carl G over 3 years
    @BergP you will probably need to provide more of the error message. I would recommend creating a new question that references this answer. You can link to your question from this answer.
  • RichieHH
    RichieHH about 3 years
    Very interesting. But enough there for me to think "nope" - I'll do without idle. Python infrastructure is a complete and utter mess.
  • infinity_coding7
    infinity_coding7 almost 3 years
    I got the same error message as Carl G. Then I tried this method and it works for me. The step 7 is the key to solve the problem in this post, where you need to point python-build to use the correct version of tcl-tk before you run pyenv install 3.x.x
  • SynackSA
    SynackSA almost 3 years
    This doesn't help when using pyenv
  • Nick
    Nick over 2 years
    I tried this on an M1 Mac, but unfortunately the last step "pyenv install 3.x.x" (where I did 3.7.9) gives a "BUILD FAILURE". I guess it's some complicated M1 Mac issue and I'll have to use home-brew in x86 mode but that's annoying...