简体   繁体   English

无法在 MacOS 上使用 pyenv Pythons 安装 tkinter

[英]Unable to install tkinter with pyenv Pythons on MacOS

Versions of Python installed via pyenv fail to import tkinter :通过 pyenv 安装的 Python 版本无法导入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:或者您可能会收到有关 header 版本与二进制文件不匹配的消息:

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)

TL;DR set the env. TL;DR 设置环境。 vars.变量。 mentioned in tcl-tk 's caveats and this GitHub comment when installing new Pythons via pyenv to get tkinter .在提到tcl-tk的告诫这个GitHub的评论通过pyenv安装新的蟒蛇时获得tkinter

First, ensure you have the latest tcl-tk via homebrew and then pay attention to its caveats:首先,确保您通过自制软件拥有最新的tcl-tk ,然后注意其警告:

※ 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 , eg from this comment .您还需要了解 pyenv 的PYTHON_CONFIGURE_OPTS--with-tcltk-includes--with-tcltk-libs ,例如来自此评论

Next, reinstall Python with the environment variables active:接下来,在环境变量处于活动状态的情况下重新安装 Python:

※ 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.如果您收到以下错误,您可能缺少PYTHON_CONFIGURE_OPTS 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)

Here is step by step guide to make tkinter (and IDLE) work if you use pyenv for Python environments management on macOS:这里是一步一步的指导,使tkinter (和IDLE)如果你用工作pyenv的Python环境在MacOS管理:

  1. install tcl-tk with Homebrew.使用 Homebrew 安装tcl-tk In shell run brew install tcl-tk在 shell 中运行brew install tcl-tk
  2. in shell run echo 'export PATH="/usr/local/opt/tcl-tk/bin:$PATH"' >> ~/.zshrc在 shell 中运行echo 'export PATH="/usr/local/opt/tcl-tk/bin:$PATH"' >> ~/.zshrc
  3. reload shell by quitting Terminal app or run source ~/.zshrc通过退出Terminal应用程序或运行source ~/.zshrc重新加载 shell
  4. after reloaded check that tck-tk is in $PATH .重新加载后检查tck-tk是否在$PATH Run echo $PATH | grep --color=auto tcl-tk运行echo $PATH | grep --color=auto tcl-tk echo $PATH | grep --color=auto tcl-tk . echo $PATH | grep --color=auto tcl-tk As the result you should see your $PATH contents with tcl-tk highlighted结果,您应该看到突出显示了tcl-tk $PATH 内容
  5. now we run three commands from Homebrew's output from step #1现在我们从第 1 步的 Homebrew 输出中运行三个命令
    1. in shell run export LDFLAGS="-L/usr/local/opt/tcl-tk/lib"在 shell 中运行export LDFLAGS="-L/usr/local/opt/tcl-tk/lib"
    2. in shell run export CPPFLAGS="-I/usr/local/opt/tcl-tk/include"在 shell 中运行export CPPFLAGS="-I/usr/local/opt/tcl-tk/include"
    3. in shell run export PKG_CONFIG_PATH="/usr/local/opt/tcl-tk/lib/pkgconfig"在 shell 中运行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> .如果您已经使用pyenv安装了 Python 版本,则使用pyenv uninstall <your python version>卸载它。 Eg pyenv uninstall 3.8.2例如pyenv uninstall 3.8.2
  7. set environment variable that will be used by python-build .设置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.在 shell 中运行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'"注意:将来使用实际安装 Homebrew 的tck-tk版本。 At the moment of posting 8.6 was the actual在发布时8.6是实际的
  8. finally install Python with pyenv with pyenv install <version> .最后用安装Python pyenvpyenv install <version> Eg pyenv install 3.8.2例如pyenv install 3.8.2

Test测试

  1. in shell run pyenv global <verion that you've just installed>在 shell 中运行pyenv global <verion that you've just installed>
  2. now check IDLE.现在检查空闲。 In shell run idle .在 shell 中运行idle You should see IDLE window without any warnings and "text printed in red".您应该会看到没有任何警告的空闲窗口和“以红色打印的文本”。

IDLE 窗口从终端运行。没有警告

  1. now check tkinter .现在检查tkinter In shell run python -m tkinter -c "tkinter._test()" .在 shell 中运行python -m tkinter -c "tkinter._test()" You should see test window like on the image:您应该会看到如图所示的测试窗口:

tkinter 测试窗口

That's it!就是这样!

My environment:我的环境:

check this is something went wrong executing steps above:检查这是不是在执行上述步骤时出错:

  1. macOS Catalina macOS Catalina
  2. zsh (included in macOS Catalina) = "shell" above zsh (包含在 macOS Catalina 中)=上面的“shell”
  3. Homebrew (installed with instructions from Homebrew official website) Homebrew(根据Homebrew官网的说明安装)
  4. pyenv (installed with Homebrew and PATH updated according to pyenv official readme from GitHub) pyenv (根据来自 GitHub 的pyenv官方自述文件安装 Homebrew 和 PATH 更新)
  5. Python 3.8.x - 3.9.x (installed with pyenv install <version> command) Python 3.8.x - 3.9.x (使用pyenv install <version>命令pyenv install <version>

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:在撰写本文时,似乎tcl-tk不再是 keg-only,因此不再需要设置环境变量:

※ 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提供tkinter并通过运行简单地解决海报的问题:

※ pyenv uninstall <python version>
※ brew install tcl-tk
※ pyenv install <python version>

(FWIW, I am using MacOS Ventura on an Apple silicon processor.) (FWIW,我在 Apple 硅处理器上使用 MacOS Ventura。)

For MacOS Big Sur (11.2.3), Carl G's answer didn't work for me because I got a zlib error.对于 MacOS Big Sur (11.2.3),Carl G 的回答对我不起作用,因为我遇到了 zlib 错误。 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

Seems there is a problem with Xcode, zlib and compiler options. Xcode、zlib 和编译器选项似乎有问题。 From brew they made some patches to 3.8.0 python version.从 brew 开始,他们制作了一些补丁到 3.8.0 python 版本。

My configuration我的配置

$ sw_vers
ProductName:    macOS
ProductVersion: 11.2.3
BuildVersion:   20D91
$ clang --version
Apple clang version 12.0.0 (clang-1200.0.32.29)
Target: x86_64-apple-darwin20.3.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

This worked for me to install 3.8.0 and 3.9.0这对我来说安装 3.8.0 和 3.9.0


# Resinstall Xcode
sudo rm -rf /Library/Developer/CommandLineTools
xcode-select --install

# Install zlib and bzip2 using brew
brew reinstall zlib bzip2
 
# Install tcl-tk tkinter
brew install tcl-tk

# Uninstall previous versions from python
pyenv uninstall 3.8.0
pyenv uninstall 3.9.0

env \
  PATH="$(brew --prefix tcl-tk)/bin:$PATH" \
  LDFLAGS="-L$(brew --prefix tcl-tk)/lib -L$(brew --prefix zlib)/lib -L$(brew --prefix bzip2)/lib" \
  CPPFLAGS="-I$(brew --prefix tcl-tk)/include -L$(brew --prefix zlib)/include -L$(brew --prefix bzip2)/include" \
  PKG_CONFIG_PATH="$(brew --prefix tcl-tk)/lib/pkgconfig" \
  CFLAGS="-I$(brew --prefix tcl-tk)/include -I$(brew --prefix openssl)/include -I$(brew --prefix bzip2)/include -I$(brew --prefix zlib)/include -I$(brew --prefix readline)/include -I$(xcrun --show-sdk-path)/usr/include" \
  LDFLAGS="-I$(brew --prefix tcl-tk)/lib -L$(brew --prefix openssl)/lib -L$(brew --prefix readline)/lib -L$(brew --prefix zlib)/lib -L$(brew --prefix bzip2)/lib"
  pyenv install --patch 3.8.3 < <(curl -sSL https://github.com/python/cpython/commit/8ea6353.patch\?full_index\=1)
  
env \
  PATH="$(brew --prefix tcl-tk)/bin:$PATH" \
  LDFLAGS="-L$(brew --prefix tcl-tk)/lib -L$(brew --prefix zlib)/lib -L$(brew --prefix bzip2)/lib" \
  CPPFLAGS="-I$(brew --prefix tcl-tk)/include -L$(brew --prefix zlib)/include -L$(brew --prefix bzip2)/include" \
  PKG_CONFIG_PATH="$(brew --prefix tcl-tk)/lib/pkgconfig" \
  CFLAGS="-I$(brew --prefix tcl-tk)/include -I$(brew --prefix openssl)/include -I$(brew --prefix bzip2)/include -I$(brew --prefix zlib)/include -I$(brew --prefix readline)/include -I$(xcrun --show-sdk-path)/usr/include" \
  LDFLAGS="-I$(brew --prefix tcl-tk)/lib -L$(brew --prefix openssl)/lib -L$(brew --prefix readline)/lib -L$(brew --prefix zlib)/lib -L$(brew --prefix bzip2)/lib"
  pyenv install 3.9.0

My sources:我的消息来源:

I had the same issue when I tried to install tkinter through pyenv.我有同样的问题,当我试图安装tkinter通过pyenv。 I was able to fix it using the following in case someone has the same problem and still want to stick with pyenv .如果有人遇到同样的问题并且仍然想坚持使用pyenv我可以使用以下方法修复它。

The Fix修复

  1. I followed @nickolay instructions to install tkinter and set the path the proper way.我跟着@nickolay说明安装tkinter ,并设置路径的正确方法。

  2. Then, I installed anaconda3-2020.07 using the pyenv install anaconda3-2020.07 command.然后,我使用pyenv install anaconda3-2020.07命令pyenv install anaconda3-2020.07

  3. 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.因为我使用的全球pyenv蟒蛇3.8.6:我导航到该文件夹我想使用Tkinter的和所使用的anaconda3-2020.07利用命令在本地pyenv local anaconda3-2020.07在特定的文件夹使用此版本pyenv的。 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注意:我在.bash_profile使用以下脚本在 cd 所需目录时自动触发 virtualenv

# 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 -)"

For Python 3.9 and above version, you can use the following formula对于 Python 3.9 及以上版本,可以使用以下公式

brew install python-tk@3.9 brew 安装 python-tk@3.9

It will instal python@3.9 and tcl-tk and bind them for you.它将安装 python@3.9 和 tcl-tk 并为您绑定它们。

Using tkinter with pyenv can be tricky due to missing dependencies.由于缺少依赖项,将tkinterpyenv一起使用可能会很棘手。

The following two steps should help you fix the tkinter and pyenv issue.以下两个步骤应该可以帮助您修复tkinterpyenv问题。

Step 1: Installing Necessary System Packages第 1 步:安装必要的系统包

Using tkinter with pyenv can be tricky due to missing dependencies.由于缺少依赖项,将tkinterpyenv一起使用可能会很棘手。

First, let's make sure we have installed the necessary system packages for tkinter .首先,让我们确保我们已经为tkinter安装了必要的系统包。

On macOS, you can use Homebrew:在 macOS 上,您可以使用 Homebrew:

brew install tcl-tk

Step 2: Linking the Correct Tcl/Tk Versions第 2 步:链接正确的 Tcl/Tk 版本

Next, make sure you link the correct versions of Tcl/Tk when installing Python. pyenv builds Python in your environment, but if you don't have the required dependencies, like the Tk/Tcl libraries, it'll build Python without them.接下来,确保在安装 Python 时链接正确版本的 Tcl/ pyenv在您的环境中构建 Python,但如果您没有所需的依赖项,如 Tk/Tcl 库,它将在没有它们的情况下构建 Python。

If the Python version you want to use is already installed on your system, you'll need to uninstall it before proceeding.如果您要使用的 Python 版本已安装在您的系统上,您需要先将其卸载,然后再继续。 For example:例如:

pyenv uninstall 3.11.3

When installing a new Python version with pyenv , use the following commands:使用pyenv安装新的 Python 版本时,使用以下命令:

For macOS, after installing tcl-tk with brew:对于 macOS,在使用 brew 安装 tcl-tk 之后:

brew install openssl readline sqlite3 xz zlib

env LDFLAGS="-L$(brew --prefix openssl@1.1)/lib -L$(brew --prefix readline)/lib -L$(brew --prefix sqlite3)/lib -L$(brew --prefix xz)/lib -L$(brew --prefix zlib)/lib -L$(brew --prefix tcl-tk)/lib" \
CPPFLAGS="-I$(brew --prefix openssl@1.1)/include -I$(brew --prefix readline)/include -I$(brew --prefix sqlite3)/include -I$(brew --prefix xz)/include -I$(brew --prefix zlib)/include -I$(brew --prefix tcl-tk)/include" \
PKG_CONFIG_PATH="$(brew --prefix openssl@1.1)/lib/pkgconfig:$(brew --prefix readline)/lib/pkgconfig:$(brew --prefix sqlite3)/lib/pkgconfig:$(brew --prefix xz)/lib/pkgconfig:$(brew --prefix zlib)/lib/pkgconfig:$(brew --prefix tcl-tk)/lib/pkgconfig" \
pyenv install <version>

Replace <version> with the version of Python you want to install.<version>替换为您要安装的版本 Python。 After that, you should be able to import tkinter in your pyenv Python environment.之后,您应该可以在pyenv Python 环境中导入tkinter

Note that I couldn't get tkinter to work with pyenv on Python 3.11.0 , but it worked perfectly on 3.11.2 .请注意,我无法让tkinter在 Python 3.11.0上使用pyenv ,但它在3.11.2上运行良好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM