2011-10-25 23 views
11

Sto usando Python 2.6 e PyGTK 2.22.6 da all-in-one installer su Windows XP, cercando di creare un eseguibile a file singolo (tramite py2exe) per la mia app.Raggruppamento delle risorse GTK con py2exe

mio problema è che quando faccio funzionare la mia applicazione come script (es. Non integrato in un file .exe, proprio come una raccolta disomogenea di .py file), che utilizza il tema nativo aspetto di Windows, ma quando ho eseguito il exe costruito Vedo il tema GTK predefinito.

So che questo problema può essere risolto copiando un mucchio di file nella directory dist creata da py2exe, ma tutto ciò che ho letto riguarda la copia manuale dei dati, mentre voglio che questa sia una parte automatica della build processi. Inoltre, tutto sull'argomento (incluso the FAQ) non è aggiornato: PyGTK ora conserva i suoi file in C:\Python2x\Lib\site-packages\gtk-2.0\runtime\... e la semplice copia delle directory lib e etc non risolve il problema.

Le mie domande sono:

  1. Mi piacerebbe essere in grado di trovare a livello di codice i dati di runtime GTK in setup.py piuttosto che percorsi di codifica duri. Come faccio a fare questo?

  2. Quali sono le risorse minime che è necessario includere?

Aggiornamento: forse ho quasi risposto # 2 per tentativi ed errori. (. Es MS Windows) per il "buono a nulla" tema al lavoro, ho bisogno dei file da:

runtime\lib\gtk-2.0\2.10.0\engines\libwimp.dll 
runtime\etc\gtk-2.0\gtkrc 
runtime\share\icons\* 
runtime\share\themes\MS-Windows 

... senza il prefisso runtime, ma per il resto con la stessa struttura di directory, seduto direttamente nella directory dist prodotto da py2exe. Ma da dove proviene il 2.10.0, dato che gtk.gtk_version è (2,22,0)?

risposta

9

Rispondere alla mia domanda qui, ma se qualcuno sa meglio sentiti libero di rispondere anche tu. Alcuni di essi sembrano abbastanza fragili (ad esempio i numeri di versione nei percorsi), quindi commenta o modifica se conosci un modo migliore.

1. Trovare i file

In primo luogo, io uso questo codice per trovare realmente la radice del runtime GTK. Questo è molto specifico per il modo di installare il runtime, però, e probabilmente potrebbe essere migliorata con una serie di controlli per le posizioni comuni:

#gtk file inclusion 
import gtk 
# The runtime dir is in the same directory as the module: 
GTK_RUNTIME_DIR = os.path.join(
    os.path.split(os.path.dirname(gtk.__file__))[0], "runtime") 

assert os.path.exists(GTK_RUNTIME_DIR), "Cannot find GTK runtime data" 

2. Quali file da includere

Questo dipende da (a) quanto è grande una dimensione di preoccupazione e (b) il contesto della distribuzione dell'applicazione. Con questo intendo, lo stai distribuendo in tutto il mondo in cui chiunque può avere impostazioni locali arbitrarie, o è solo per uso interno aziendale in cui non hai bisogno di stringhe di titoli tradotte?

Se volete tematizzazione di Windows, è necessario includere:

GTK_THEME_DEFAULT = os.path.join("share", "themes", "Default") 
GTK_THEME_WINDOWS = os.path.join("share", "themes", "MS-Windows") 
GTK_GTKRC_DIR = os.path.join("etc", "gtk-2.0") 
GTK_GTKRC = "gtkrc" 
GTK_WIMP_DIR = os.path.join("lib", "gtk-2.0", "2.10.0", "engines") 
GTK_WIMP_DLL = "libwimp.dll" 

Se si desidera che le icone Tango:

GTK_ICONS = os.path.join("share", "icons") 

C'è anche dati di localizzazione (che tralascio, ma si potrebbe non vogliono):

GTK_LOCALE_DATA = os.path.join("share", "locale") 

3. Mettendo insieme

In primo luogo, ecco una funzione che guida l'albero del filesystem in un dato punto e produce un'uscita adatta all'opzione data_files.

def generate_data_files(prefix, tree, file_filter=None): 
    """ 
    Walk the filesystem starting at "prefix" + "tree", producing a list of files 
    suitable for the data_files option to setup(). The prefix will be omitted 
    from the path given to setup(). For example, if you have 

     C:\Python26\Lib\site-packages\gtk-2.0\runtime\etc\... 

    ...and you want your "dist\" dir to contain "etc\..." as a subdirectory, 
    invoke the function as 

     generate_data_files(
      r"C:\Python26\Lib\site-packages\gtk-2.0\runtime", 
      r"etc") 

    If, instead, you want it to contain "runtime\etc\..." use: 

     generate_data_files(
      r"C:\Python26\Lib\site-packages\gtk-2.0", 
      r"runtime\etc") 

    Empty directories are omitted. 

    file_filter(root, fl) is an optional function called with a containing 
    directory and filename of each file. If it returns False, the file is 
    omitted from the results. 
    """ 
    data_files = [] 
    for root, dirs, files in os.walk(os.path.join(prefix, tree)):   
     to_dir = os.path.relpath(root, prefix) 

     if file_filter is not None: 
      file_iter = (fl for fl in files if file_filter(root, fl)) 
     else: 
      file_iter = files 

     data_files.append((to_dir, [os.path.join(root, fl) for fl in file_iter])) 

    non_empties = [(to, fro) for (to, fro) in data_files if fro] 

    return non_empties 

Così ora si può chiamare setup() in questo modo:

setup(
    # Other setup args here... 

    data_files = (
        # Use the function above... 
        generate_data_files(GTK_RUNTIME_DIR, GTK_THEME_DEFAULT) + 
        generate_data_files(GTK_RUNTIME_DIR, GTK_THEME_WINDOWS) + 
        generate_data_files(GTK_RUNTIME_DIR, GTK_ICONS) + 

        # ...or include single files manually 
        [ 
         (GTK_GTKRC_DIR, [ 
          os.path.join(GTK_RUNTIME_DIR, 
           GTK_GTKRC_DIR, 
           GTK_GTKRC) 
         ]), 

         (GTK_WIMP_DIR, [ 
          os.path.join(
           GTK_RUNTIME_DIR, 
           GTK_WIMP_DIR, 
           GTK_WIMP_DLL) 
         ]) 
        ] 
       ) 
)