TK Framework double implementation issue TK Framework double implementation issue tkinter tkinter

TK Framework double implementation issue


I know I created the bounty, but I got impatient, decided to investigate, and now I've got something that worked for me. I have a very similar python example to yours, which pretty much does nothing other than try to use Tkinter to display an image passed on the command line, like so:

calebhattingh $ python imageview.py a.jpgobjc[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

What's happening is that the binary file, ~/anaconda/envs/py35/lib/python3.5/site-packages/PIL/_imagingtk.so has been linked to a framework, and not the Tcl/Tk libs in the env. You can see this by using otool to see the linking setup:

(py35)🎨  ~/anaconda/envs/py35/lib/python3.5/site-packages/PILcalebhattingh $ 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)

See those two "framework" lines? With anaconda we don't want that. We want to use the libraries in the env. So let's change them!

First make a backup of your binary (in case you want to revert):

$ cp _imagingtk.so _imagingtk.so.bak

Now run this on the command-line (assuming you are in the same folder as your 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

You see that @rpath bit in there? That means whichever one you find on the path. Which works great for anaconda. The linking in the _imagingtk.so library now looks like this:

(py35)🎨  ~/anaconda/envs/py35/lib/python3.5/site-packages/PILcalebhattingh $ 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)

After this, your code will run. Someone should probably try to get this upstream.

Addendum: The Tkinter binding in the python distribution, i.e., the currently-active conda env, has the following linking:

🎨  ~/anaconda/envs/py35/lib/python3.5/lib-dynloadcalebhattingh $ 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)

If you prefer, you can rather use install_name_tool to use @loader_path/../../ instead of what I used above, i.e. @rpath/. That will probably also work, and might even be better.


I try to conduct my own investigation of this problem (in my case that was problem with matplotlib)

  • I try to found binaries, linked with System Tcl/Tk Library paths
  • With libraries i found file, which seems really interesting. It has name name osx-tk.patch and was placed in ~/anaconda/pkgs/matplotlib-1.5.1-np111py35_0/info/recipe/
  • Found osx-tk.patch sources into GitHub

  • After reading the patch and Conda documentation i became finally convinced about wrong package installation, and i remember, that i used pip for matplotlib installation!

  • I deleted old package with pip and install new one with conda install matplotlib command

  • Now everything started to work like a charm!

Brief summary:

Using pip package manager with conda environment, i messed my dependencies, because conda may using special recipes, that point installer how to install package correctly in conda virtual environment

Ultra-Brief summary:

Delete package fully with dependencies and install it again with conda package manager (use rebinding only in difficult cases)


I did exactly what @cjrh said for _imagetk.so, but instead for _tkinter.so in ~/anaconda/lib/python3.5/lib-dynload/ and it worked great!

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