Reputation: 18250
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)
Upvotes: 74
Views: 35359
Reputation: 135
To expand on the answer provided by @Carl g for Fish shell and/or Poetry users and assuming brew
users
To make sure you can use your chosen python version
brew upgrade pyenv
Set correct shell variable for Fish shell users
# Fish specific
set PATH "$(brew --prefix tcl-tk)/bin:$PATH"
set LDFLAGS "-L$(brew --prefix tcl-tk)/lib"
set CPPFLAGS "-I$(brew --prefix tcl-tk)/include"
set PKG_CONFIG_PATH "$(brew --prefix tcl-tk)/lib/pkgconfig"
set CFLAGS "-I$(brew --prefix tcl-tk)/include"
set 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'"
In the same shell session, install your python version
pyenv install 3.12.6
Make it the default python installation
pyenv global 3.12.6
However I had some homebrew python version at /opt/homebrew/opt/[email protected]/Frameworks/Python.framework/Versions/3.12
which poetry did keep using even setting pyenv global
so to force the newly compiled python version:
Remove the current associated venv associated with the poetry project
poetry env remove --all
Get pyenv python path
pyenv which python
# /Users/hayer/.pyenv/versions/3.12.6/bin/python
Use path as argument for poetry
poetry env use /Users/hayer/.pyenv/versions/3.12.6/bin/python
To test your python
poetry shell
# Spawns new shell with python activated
# Start python session
python
# Python 3.12.6
import tkinter
# Should not result in errors
For UV users
At the moment of writing it is not possible to compile Python with other settings or that UV provides workable tkinter
out of the box See this Github Issue
Upvotes: 0
Reputation: 141
At the time of this writing, it appears that tcl-tk
is no longer keg-only and, therefore, setting environment variables is no longer needed:
※ brew info tcl-tk
==> tcl-tk: stable 8.6.13 (bottled)
...
==> Caveats
The sqlite3_analyzer binary is in the `sqlite-analyzer` formula.
==> Analytics
...
Indeed, I was able to provide pyenv
with tkinter
and solve the poster's problem simply by running:
※ pyenv uninstall <python version>
※ brew install tcl-tk
※ pyenv install <python version>
(FWIW, I am using MacOS Ventura on an Apple silicon processor.)
Upvotes: 14
Reputation: 3863
Here is step by step guide to make tkinter
(and IDLE) work if you use pyenv
for Python environments management on macOS:
tcl-tk
with Homebrew. In shell run brew install tcl-tk
echo 'export PATH="/usr/local/opt/tcl-tk/bin:$PATH"' >> ~/.zshrc
Terminal
app or run source ~/.zshrc
tcl-tk
is in $PATH
. Run echo $PATH | grep --color=auto tcl-tk
. As the result you should see your $PATH contents with tcl-tk
highlightedexport 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"
pyenv
then uninstall it with pyenv uninstall <your python version>
. E.g. pyenv uninstall 3.8.2
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 actualpyenv
with pyenv install <version>
. E.g. pyenv install 3.8.2
Test
pyenv global <verion that you've just installed>
idle
. You should see IDLE window without any warnings and "text printed in red".tkinter
. In shell run python -m tkinter -c "tkinter._test()"
. You should see test window like on the image:That's it!
My environment:
check this is something went wrong executing steps above:
zsh
(included in macOS Catalina) = "shell" abovepyenv
(installed with Homebrew and PATH updated according to pyenv
official readme from GitHub)3.8.x
- 3.9.x
(installed with pyenv install <version>
command)Upvotes: 56
Reputation: 1108
For Python 3.9 and above version, you can use the following formula
brew install [email protected]
It will instal [email protected] and tcl-tk and bind them for you.
Upvotes: -1
Reputation: 363
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
Upvotes: 1
Reputation: 1190
I had the same issue when I tried to install tkinter
through pyenv. I was able to fix it using the following in case someone has the same problem and still want to stick with pyenv
.
The Fix
I followed @nickolay instructions to install tkinter
and set the path the proper way.
Then, I installed anaconda3-2020.07 using the pyenv install anaconda3-2020.07
command.
Because I am using pyenv python 3.8.6 globally: I navigated to the folder I want to use tkinter and used the anaconda3-2020.07
locally by utilizing the command pyenv local anaconda3-2020.07
to use this version of pyenv in that specific folder. It ran without errors!
Note: I am using the following script in the .bash_profile
to trigger the virtualenv automatically when cd the desired directory
# manage python version using pyenv
if command -v pyenv 1>/dev/null 2>&1; then
eval "$(pyenv init -)"
fi
# add pyenv virtualenv
eval "$(pyenv virtualenv-init -)"
Upvotes: 0
Reputation: 18250
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)
Upvotes: 135