问题 TK Framework双重实施问题


我正在测试使用Tkinter模块创建GUI。我试图使用PIL将图像添加到GUI。我的代码如下所示:

import Tkinter as tk
from PIL import Image, ImageTk

root = tk.Tk()
root.title('background image')

imfile = "foo.png"
im = Image.open(imfile)
im1 = ImageTk.PhotoImage(im)

当我运行此代码时,我想出了一些导致段错误的错误。

objc[5431]: Class TKApplication is implemented in both/Users/sykeoh/anaconda/lib/libtk8.5.dylib and /System/Library/Frameworks/Tk.framework/Versions/8.5/Tk. One of the two will be used. Which one is undefined.
objc[5431]: Class TKMenu is implemented in both /Users/sykeoh/anaconda/lib/libtk8.5.dylib and /System/Library/Frameworks/Tk.framework/Versions/8.5/Tk. One of the two will be used. Which one is undefined.
objc[5431]: Class TKContentView is implemented in both /Users/sykeoh/anaconda/lib/libtk8.5.dylib and /System/Library/Frameworks/Tk.framework/Versions/8.5/Tk. One of the two will be used. Which one is undefined.
objc[5431]: Class TKWindow is implemented in both /Users/sykeoh/anaconda/lib/libtk8.5.dylib and /System/Library/Frameworks/Tk.framework/Versions/8.5/Tk. One of the two will be used. Which one is undefined.
Segmentation fault: 11

我在网上看了一下,看起来我的系统库中的Tk框架和anaconda库中的另一个问题。但是,这些解决方案似乎都没有起作用。任何可能的解决方案或解决方法?

运行ImageTk.Photoimage会出现问题。如果删除该行代码,则没有问题。


4604
2018-02-24 04:59


起源

你可以运行相同的代码吗? IDLE 还是终端?如果这是一个 anaconda 您可能需要提供有关设置的更具体信息的具体问题 - Tadhg McDonald-Jensen
可以肯定的是,您使用的是原始PIL还是Pillow? - Jordon Birk


答案:


我知道我创造了赏金,但我不耐烦,决定调查,现在我有一些对我有用的东西。我有一个非常类似的python示例,除了尝试使用Tkinter显示在命令行上传递的图像之外几乎什么也没做,如下所示:

calebhattingh $ python imageview.py a.jpg
objc[84696]: Class TKApplication is implemented in both /Users/calebhattingh/anaconda/envs/py35/lib/libtk8.5.dylib and /System/Library/Frameworks/Tk.framework/Versions/8.5/Tk. One of the two will be used. Which one is undefined.
objc[84696]: Class TKMenu is implemented in both /Users/calebhattingh/anaconda/envs/py35/lib/libtk8.5.dylib and /System/Library/Frameworks/Tk.framework/Versions/8.5/Tk. One of the two will be used. Which one is undefined.
objc[84696]: Class TKContentView is implemented in both /Users/calebhattingh/anaconda/envs/py35/lib/libtk8.5.dylib and /System/Library/Frameworks/Tk.framework/Versions/8.5/Tk. One of the two will be used. Which one is undefined.
objc[84696]: Class TKWindow is implemented in both /Users/calebhattingh/anaconda/envs/py35/lib/libtk8.5.dylib and /System/Library/Frameworks/Tk.framework/Versions/8.5/Tk. One of the two will be used. Which one is undefined.
Segmentation fault: 11

发生了什么事情 二进制 文件, ~/anaconda/envs/py35/lib/python3.5/site-packages/PIL/_imagingtk.so 已链接到框架,而不是环境中的Tcl / Tk库。你可以通过使用来看到这一点 otool 看到链接设置:

(py35)  ~/anaconda/envs/py35/lib/python3.5/site-packages/PIL
calebhattingh $ otool -L _imagingtk.so 
_imagingtk.so:
        /System/Library/Frameworks/Tcl.framework/Versions/8.5/Tcl (compatibility version 8.5.0, current version 8.5.9)
        /System/Library/Frameworks/Tk.framework/Versions/8.5/Tk (compatibility version 8.5.0, current version 8.5.9)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
        /usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)

看到那两个“框架”线?有了anaconda,我们不希望这样。我们想要使用env中的库。所以让我们改变它们吧!

首先备份二进制文件(如果你想恢复):

$ cp _imagingtk.so _imagingtk.so.bak

现在在命令行上运行它(假设你和你的文件夹在同一个文件夹中) envname/lib):

$ install_name_tool -change "/System/Library/Frameworks/Tk.framework/Versions/8.5/Tk" "@rpath/libtk8.5.dylib" _imagingtk.so
$ install_name_tool -change "/System/Library/Frameworks/Tcl.framework/Versions/8.5/Tcl" "@rpath/libtcl8.5.dylib" _imagingtk.so

你看到了 @rpath 在那里?这意味着 无论你在路上找到哪一个。这适用于anaconda。链接在 _imagingtk.so 库现在看起来像这样:

(py35)  ~/anaconda/envs/py35/lib/python3.5/site-packages/PIL
calebhattingh $ otool -L _imagingtk.so
_imagingtk.so:
        @rpath/libtcl8.5.dylib (compatibility version 8.5.0, current version 8.5.9)
        @rpath/libtk8.5.dylib (compatibility version 8.5.0, current version 8.5.9)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
        /usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)

在此之后,您的代码将运行。有人应该尝试将其上游。

附录:python发行版中的Tkinter绑定,即当前活动的conda env,具有以下链接:

  ~/anaconda/envs/py35/lib/python3.5/lib-dynload
calebhattingh $ otool -L _tkinter.cpython-35m-darwin.so 
_tkinter.cpython-35m-darwin.so:
        @loader_path/../../libtcl8.5.dylib (compatibility version 8.5.0, current version 8.5.18)
        @loader_path/../../libtk8.5.dylib (compatibility version 8.5.0, current version 8.5.18)
        /usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.0.0)

如果您愿意,可以选择使用 install_name_tool 使用 @loader_path/../../ 而不是我上面使用的,即 @rpath/。那会的 大概 也工作,甚至可能更好。


9
2018-05-14 04:03



这对我有用,谢谢!此外,您可以通过简单的命令找到链接到系统Tkinter的二进制文件: grep -rnw 'Tk.framework '  和 grep -rnw 'Tcl.framework ' - lucidyan
非常感谢你。这是Conda中的一个错误吗? - Gus
不,我认为这与Pillow有关。如果包是一个conda包,那么bug就是pkg没有正确构建。如果软件包是pip安装的(我不记得了),那么这个bug就是我期望安装到conda环境中的非conda软件包可以工作;) - Caleb Hattingh


我尝试对这个问题进行自己的调查(在我的情况下,这是matplotlib的问题)

  • 我尝试找到与系统Tcl / Tk库路径链接的二进制文件
  • 使用库我找到了文件,这看起来很有趣。它有名称 osx-tk.patch 并被安置在 ~/anaconda/pkgs/matplotlib-1.5.1-np111py35_0/info/recipe/
  • 发现 osx-tk.patch 来源 GitHub上

  • 看完补丁后 Conda文档 我终于确信错误的包安装,我记得,我用过 pip 用于matplotlib安装!

  • 我删了旧包 pip 并安装新的 conda install matplotlib 命令

  • 现在一切都开始像魅力一样!

简要总结:

运用 pip 带有conda环境的包管理器,我弄乱了我的依赖项,因为conda可能使用特殊的 食谱,那点安装程序如何在conda虚拟环境中正确安装包

超简要总结:

使用依赖项完全删除包并使用conda包管理器再次安装它(仅在困难的情况下使用重新绑定)


2
2018-05-20 20:29



这是一个我没有考虑过的非常有趣的观点。我很确定我通过conda安装Pillow,但是仍然值得考虑其他情况,其中包与conda和pip安装在同一个env中。 - Caleb Hattingh


我完全按照@cjrh的说法做了 _imagetk.so,而是为了 _tkinter.so 在 ~/anaconda/lib/python3.5/lib-dynload/ 它工作得很好!

cd ~/anaconda/lib/python3.5/lib-dynload

$ install_name_tool -change "/System/Library/Frameworks/Tk.framework/Versions/8.5/Tk" "@rpath/libtk8.5.dylib" _tkinter.so
$ install_name_tool -change "/System/Library/Frameworks/Tcl.framework/Versions/8.5/Tcl" "@rpath/libtcl8.5.dylib" _tkinter.so

0
2017-09-06 22:33