2016-02-24 5 views
11

Ich teste out Erstellen einer GUI mit dem Tkinter-Modul. Ich habe versucht, ein Bild mit PIL der GUI hinzuzufügen. Mein Code sieht wie folgt aus:TK-Framework doppelte Implementierung Problem

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) 

Wenn ich diesen Code ausführen, ich mit einigen Fehlern kommen, die zu einem segfault führen.

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 

Ich habe Online sah und sieht es ein Problem mit dem Tk Rahmen in meiner Systeme Bibliothek und die andere in der Anakonda Bibliothek. Keine der Lösungen schien wirklich zu funktionieren. Irgendwelche möglichen Lösungen oder Workarounds?

Das Problem kommt mit dem Ausführen von ImageTk.Photoimage. Wenn ich diese Codezeile entferne, gibt es keine Probleme.

+0

können Sie den gleichen Code in 'IDLE' oder Terminal laufen? Wenn dies eine "anaconda" spezifische Frage ist, müssen Sie möglicherweise genauere Informationen über die Einrichtung geben. –

+0

Nur um sicher zu sein, verwenden Sie das Original PIL oder Pillow? –

Antwort

9

Ich weiß, dass ich das Kopfgeld geschaffen habe, aber ich wurde ungeduldig, entschied mich zu untersuchen, und jetzt habe ich etwas, das für mich funktionierte. Ich habe ein sehr ähnliches Python Beispiel zu Ihnen, was ziemlich viel macht nichts anderes, als versuchen, Tkinter zu verwenden, um ein Bild auf der Kommandozeile, wie so übergab anzuzeigen:

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 

passiert Was ist, dass die binäre Datei , ~/anaconda/envs/py35/lib/python3.5/site-packages/PIL/_imagingtk.so wurde mit einem Framework verknüpft und nicht mit den Tcl/Tk-Bibliotheken im env. Sie können dies sehen durch otool mit der Verknüpfung von Setup zu sehen:

(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) 

Siehst du die beiden „Rahmen“ Linien? Mit Anaconda wollen wir das nicht. Wir wollen die Bibliotheken im env verwenden. Also lass uns sie ändern!

Zuerst machen Sie eine Sicherungskopie Ihrer binary (im Fall, dass Sie zurücksetzen):

$ cp _imagingtk.so _imagingtk.so.bak 

Nun ist diese laufen auf der Kommandozeile (vorausgesetzt, Sie im selben Ordner wie die envname/lib sind):

$ 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 

Sie sehen, dass @rpath Bit drin? Das bedeutet, je nachdem, was Sie auf dem Pfad finden. Was gut für Anakonda funktioniert. Die Verknüpfung in der _imagingtk.so Bibliothek sieht nun wie folgt aus:

(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) 

Danach wird Ihr Code ausführen. Jemand sollte wahrscheinlich versuchen, das upstream zu bekommen.

Nachtrag: Die Tkinter in der Python-Distribution zu binden, dh die gegenwärtig aktive Conda env, hat die folgende Verknüpfung:

~/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) 

Wenn Sie möchten, können Sie eher install_name_tool verwenden @loader_path/../../ stattdessen zu verwenden von dem, was ich oben verwendet habe, dh @rpath/. Das wird wahrscheinlich auch funktionieren, und könnte sogar besser sein.

+1

Es hat für mich funktioniert, danke! Sie können auch Binärdateien finden, die durch einfache Befehle mit dem System Tkinter verbunden sind: 'grep -rnw 'Tk.framework'' und 'grep -rnw 'Tcl.framework'' – lucidyan

+0

Vielen Dank dafür. Ist das ein Fehler in Conda? – Gus

+0

Nein, ich denke, es geht um Kissen. Wenn das Paket ein Conda-Paket war, dann ist der Fehler, dass das Paket nicht korrekt erstellt wurde. Wenn das Paket pip-installiert wurde (ich kann mich nicht erinnern), dann war der Fehler, dass ich ein non-conda-Paket in einer conda-Umgebung installieren würde;) –

2

Ich versuche, meine eigene Untersuchung dieses Problems (in meinem Fall, das Problem mit matplotlib war) zu leiten

  • ich gefunden Binärdateien versuchen, verbunden mit dem System Tcl/Tk-Bibliothek Pfaden
  • Mit Bibliotheken i Datei gefunden, die wirklich interessant scheint. Es hat den Namen Name osx-tk.patch und wurde in ~/anaconda/pkgs/matplotlib-1.5.1-np111py35_0/info/recipe/
  • Gefunden osx-tk.patch Quellen in GitHub

  • Nach dem Lesen des Patch und Conda documentation ich über falsche Paketinstallation wurde schließlich überzeugt platziert, und ich erinnere mich, dass ich pip für matplotlib Installation verwendet !

  • ich alte Paket mit pip gelöscht und neue mit conda install matplotlib Befehl installieren

  • nun wie ein Zauber funktioniert alles begann!

Kurze Zusammenfassung:

Mit pip Paket-Manager mit Conda Umgebung, verwirrte ich meine Abhängigkeiten, weil Conda spezielle recipes Verwendung kann, dass Punkt-Installer, wie Paket in Conda virtueller Umgebung korrekt installieren

Ultra-Kurze Zusammenfassung:

Paket vollständig mit Abhängigkeiten löschen und installieren ag ain mit Conda Paket-Manager (Verwendung Rebinding nur in schwierigen Fällen)

+0

Dies ist ein sehr interessanter Punkt, den ich nicht berücksichtigt hatte. Ich bin ziemlich sicher, dass ich Pillow durch Conda installieren, aber es ist immer noch eine Überlegung wert für andere Situationen, in denen Pakete in der gleichen Umgebung mit Conda und Pip installiert werden. –

0

Ich tat genau das, was @cjrh für _imagetk.so sagte, sondern für _tkinter.so in ~/anaconda/lib/python3.5/lib-dynload/ und es funktionierte großartig!

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