2010-07-15 9 views
6
applicazione

mio pitone è costruito come tale che alcune funzionalità è disponibile come plugin. L'architettura del plugin al momento è molto semplice: ho una cartella/pacchetto di plugin che contiene alcuni moduli python. I caricare il plugin pertinente nel modo seguente:caricamento dinamico di plugin pitone non compilati in py2exe codice compilazione

plugin_name = blablabla 
try: 
    module = __import__(plugin_name, fromlist='do_something') 
except ImportError: 
    #some error handling ... 

e quindi eseguire:

try: 
    loans = module.do_something(id_t, pin_t) 
except xxx: 
    # error handling 

ho compilare l'applicazione a un Windows binario utilizzando py2exe. Funziona bene, tranne per il fatto che tutti i plugin sono (e devono essere) inclusi nel file binario. Questo non è molto pratico, dal momento che per ogni nuovo plugin, devo ricompilare e rilasciare una nuova versione della mia applicazione. Sarebbe meglio se un nuovo plug-in (cioè il file python) potesse essere copiato in qualche cartella di plug-in dell'applicazione e che il codice Python nel codice del file fosse interpretato al volo dalla mia applicazione.

Qual è l'approccio migliore per farlo?

(ho però di leggere ogni riga del file plugin selezionato, e l'applicazione di un exec statement ad essa. Ma ci potrebbero essere modi migliori ...)

risposta

0

vi suggerisco di utilizzare pkg_resources entry_points caratteristiche (da setuptools/Distribuisci) per implementare la scoperta e l'istanziazione dei plugin: in primo luogo, è un modo standard per farlo; in secondo luogo, non soffre il problema che hai citato AFAIK. Tutto quello che devi fare per estendere l'applicazione è di impacchettare alcuni plugin in un uovo che dichiara alcuni punti di ingresso (un uovo può dichiarare molti plugin), e quando installi quell'uovo nella tua distribuzione python, tutti i plugin che dichiara possono essere automaticamente scoperto dalla tua applicazione. Puoi anche impacchettare la tua applicazione e i plugin "factory" nello stesso uovo, è abbastanza conveniente.

+1

Grazie per la risposta. Ma questo non richiederebbe a qualcuno di avere python installato sul suo computer? (la soluzione che ho proposto, richiederebbe che, ora che ci penso) – Rabarberski

+0

Hai ragione, dovrebbe essere la stessa installazione python sia per l'applicazione che per i plugin esterni. Sono d'accordo, questo è abbastanza fastidioso. –

0

non sono sicuro devi mettere file dei plugin nella biblioteca zip. Ciò potrebbe essere dovuto al fatto che si sta utilizzando l'impostazione predefinita per lo script py2exe.

Si potrebbe provare a utilizzare compressa = False (come documentato in py2exe ListOfOptions) che eliminerebbe la library.zip generato da py2exe, e forse ti permettono di avere accesso ai moduli Python (i tuoi plugin sono moduli Python, presumo, dal import) in un modo "normale", invece di essere costretti a comprimerli nel tuo zip o binario.

1

PyInstaller consente di importare anche file esterni. Se lo si esegue sulla propria applicazione, non impacchetterà i file all'interno dell'eseguibile. Dovrai quindi assicurarti che i percorsi siano corretti (cioè, l'applicazione può trovare i moduli sul disco nella directory corretta) e tutto dovrebbe funzionare.

2

Se non ti dispiace che i plug-in siano rilasciati come file .py, puoi fare qualcosa di simile al seguente. Metti tutti i tuoi plugin sotto una sottodirectory "plugin" e crea un "__init__.py" vuoto. Facendo runtime, importerà il pacchetto insieme a tutti i moduli in quella directory. Controlla Dive In Python per la spiegazione ... ma ecco cosa ho finito per usare.

def load_plugin(path): 
    import imp 
    """Load plugin from directory and return list of modules""" 
    files = os.listdir(path) 
    test = re.compile(".py$", re.IGNORECASE)   
    files = filter(test.search, files)      
    filenameToModuleName = lambda f: os.path.splitext(f)[0] 
    moduleNames = sorted(map(filenameToModuleName, files)) 
    f, filename, desc = imp.find_module('plugin') 
    plugin = imp.load_module('plugin', f, filename, desc) 
    modules = [] 

    #print moduleNames 
    for m in moduleNames: 
     # skip any files starting with '__', such as __init__.py 
     if m.startswith('__'): 
      continue 
     try: 
      f, filename, desc = imp.find_module(m, plugin.__path__) 
      modules.append(imp.load_module(m, f, filename, desc)) 
     except ImportError: 
      continue 
    return modules 
+0

Sarebbe possibile per quei moduli caricare classi che esistono nella versione compilata? –

0

ho trovato come fare moduli esterni di importazione (in cima alla eseguibile compilato, in fase di esecuzione) con pyinstaller. calcola che originariamente il percorso dell'eseguibile è stato automaticamente aggiunto a sys.path, ma per ragioni di sicurezza lo hanno rimosso ad un certo punto. per riattivare questo, utilizzare:

sys.path.append(os.path.dirname(sys.executable)) 

questo permetterà l'importazione di file che si trovano nello stesso percorso dell'eseguibile .py. è possibile aggiungere questa linea al gancio di runtime o all'app principale.

Problemi correlati