2016-02-24 37 views
11

Sto testando la creazione di una GUI utilizzando il modulo Tkinter. Stavo cercando di aggiungere un'immagine alla GUI usando PIL. Il mio codice è simile al seguente:Problema di doppia implementazione TK Framework

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) 

Quando ho eseguito questo codice, vengo con alcuni errori che portano a un segfault.

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 

Ho guardato on-line e sembra essere un problema con il quadro Tk nella mia biblioteca sistemi e l'altro nella biblioteca anaconda. Tuttavia, nessuna delle soluzioni sembrava funzionare. Qualche possibile soluzione o soluzione alternativa?

Il problema si presenta con l'esecuzione di ImageTk.Photoimage. Se rimuovo quella riga di codice, non ci sono problemi.

+0

è possibile eseguire lo stesso codice in 'IDLE' o Terminal? Se si tratta di una domanda specifica di 'anaconda', potrebbe essere necessario fornire informazioni più specifiche sulla configurazione –

+0

Per sicurezza, stai utilizzando il PIL originale o il cuscino? –

risposta

9

So che ho creato la taglia, ma mi sono impaziente, ho deciso di indagare, e ora ho qualcosa che ha funzionato per me. Ho un pitone esempio molto simile al tuo, che praticamente fa altro che cercare di usare Tkinter per visualizzare un'immagine passata sulla linea di comando, così:

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 

Quello che sta succedendo è che il file binario , ~/anaconda/envs/py35/lib/python3.5/site-packages/PIL/_imagingtk.so è stato collegato a un framework e non alle librerie Tcl/Tk nell'env. Si può vedere questo utilizzando otool per vedere l'impostazione di collegamento:

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

vedere quelle due "quadro" linee? Con anaconda non lo vogliamo. Vogliamo utilizzare le librerie nell'env. Quindi cambiamoli!

prima fare un backup del vostro binario (nel caso in cui si desidera ripristinare):

$ cp _imagingtk.so _imagingtk.so.bak 

Ora eseguire questo su riga di comando (supponendo ci si trova nella stessa cartella del 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 

Si vede che @rpath bit in là? Ciò significa che lo si trova sul percorso. Che funziona benissimo per anaconda. Il collegamento nella biblioteca _imagingtk.so appare come segue:

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

Dopo questo, il codice verrà eseguito. Qualcuno dovrebbe probabilmente cercare di ottenere questo a monte.

Addendum: legare il Tkinter nella distribuzione pitone, vale a dire, il Conda ENV attualmente attiva, ha la seguente collegamento:

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

Se si preferisce, è possibile invece utilizzare install_name_tool da usare @loader_path/../../ invece di quello che ho usato sopra, ovvero @rpath/. Ciò funzionerà anche e potrebbe anche essere migliore.

+1

Ha funzionato per me, grazie! Inoltre, puoi trovare i binari, che sono collegati al sistema Tkinter con semplici comandi: 'grep -rnw 'Tk.framework'' e 'grep -rnw 'Tcl.framework'' – lucidyan

+0

Grazie mille per questo. Quindi questo è un bug in Conda? – Gus

+0

No, penso che abbia a che fare con il cuscino. Se il pacchetto era un pacchetto conda, il bug è che il pkg non è stato compilato correttamente. Se il pacchetto è stato pip-installato (non ricordo), il bug mi aspettava che un pacchetto non-conda installato in un ambiente conda funzionasse;) –

2

cerco di condurre la mia ricerca di questo problema (nel mio caso, che è stato un problema con matplotlib)

  • cerco di binari trovati, collegata con percorsi sistema Tcl/Tk Biblioteca
  • Con le biblioteche i file trovato, che sembra davvero interessante. Ha nome nome osx-tk.patch ed è stata posta in ~/anaconda/pkgs/matplotlib-1.5.1-np111py35_0/info/recipe/
  • Trovato osx-tk.patch fonti in GitHub

  • Dopo aver letto la patch e Conda documentation sono diventato finalmente convinto circa l'installazione del pacchetto sbagliato, e mi ricordo che ho usato pip per l'installazione matplotlib !

  • ho cancellato pacchetto vecchio con pip e installarne una nuova con conda install matplotlib comando

  • Ora tutto ha iniziato a lavorare come un fascino!

Breve sintesi:

Utilizzando pip gestore di pacchetti con l'ambiente Conda, ho incasinato le mie dipendenze, perché conda può utilizzare speciale recipes, che installatore punto come installare il pacchetto correttamente in ambiente virtuale Conda

Riepilogo Ultra-Breve:

Elimina il pacchetto completamente con dipendenze e installalo ain con gestore di pacchetti Conda (uso rebinding solo in casi difficili)

+0

Questo è un punto molto interessante che non avevo considerato. Sono abbastanza sicuro di installare Pillow tramite conda, ma vale comunque la pena di tener conto di altre situazioni in cui i pacchetti vengono installati nello stesso ambiente con conda e pip. –

0

ho fatto esattamente quello che @cjrh dire per _imagetk.so, ma, invece, per _tkinter.so in ~/anaconda/lib/python3.5/lib-dynload/ e ha funzionato grande!

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