2010-10-14 14 views
7

Sto creando un'app wxpython che compilerò con le varie utilità di congelamento disponibili per creare un eseguibile per più piattaforme.Python - Creazione di un sistema "scripting"

il programma sarà un editer mappa per una tile-based motore di gioco

in questa app voglio fornire un sistema di scripting in modo che gli utenti avanzati possono modificare il comportamento del programma, come la modifica dei dati di progetto, l'esportazione il progetto in un formato diverso ecc.

Voglio che il sistema funzioni in questo modo.

l'utente posizionerà lo script python che desidera eseguire in una casella di testo stile e quindi premere un pulsante per eseguire lo script.

Sto bene con questo finora questo è tutto molto semplice. ottenere lo script dalla casella di testo come una stringa compilarlo a un oggetto di merluzzo con la funzione di compilazione integrato() quindi eseguire lo script con uno statment exec

script = textbox.text #bla bla store the string 
code = compile(script, "script", "exec") #make the code object 
eval(code, globals()) 

la cosa è, voglio fare in modo che questa funzione non può causare errori o errori
dire se c'è una dichiarazione di importazione nello script. questo causerà problemi tenendo conto che il codice è stato compilato con qualcosa come py2exe o py2app?
Come faccio a essere sicuro che l'utente non possa interrompere la parte critica del programma come modificare parte della GUI consentendo comunque loro di modificare i dati del progetto (i dati sono conservati in proprietà globali nel proprio modulo)? Penso che ciò significherebbe modificare il ditt globale che viene passato alla funzione eval.
come assicurarsi che questo errore non possa causare il blocco del programma a causa di un ciclo lungo o infinito? come faccio a essere sicuro che un errore generato nel codice dell'utente non possa bloccare l'intera app?

In sostanza, come evitare tutti i problemi che possono sorgere quando si consente all'utente di eseguire il proprio codice?

EDIT: Per quanto riguarda le risposte date

non mi sento come una delle risposte finora hanno davvero risposto alle mie domande sì sono stati in parte risposto, ma non completamente. Sono ben consapevole dell'impossibilità di arrestare completamente il codice non sicuro. le persone sono semplicemente troppo intelligenti per un uomo (o persino un teem) per pensare a tutti i modi per aggirare un sistema di sicurezza e prevenirli.

in effetti non mi interessa davvero se lo fanno. Sono più preoccupato per qualcuno che rompe involontariamente qualcosa che non sapevano. se qualcuno volesse davvero, potrebbe strappare l'app a brandelli con la funzionalità di scripting, ma non me ne potrebbe importare di meno. sarà la loro istanza e tutti i problemi che creeranno spariranno quando riavviano l'app, a meno che non abbiano incasinato i file sull'HD. Voglio prevenire i problemi che sorgono quando l'utente dosa qualcosa di stupido.
cose come IOError's, SystaxErrors, InfiniteLoopErrors ect.

ora è stata data una risposta alla parte riguardante lo scope. Ora capisco come definire quali funzioni e globali sono accessibili dalla funzione eval ma c'è un modo per assicurarsi che l'esecuzione del loro codice possa essere interrotta se impiega troppo tempo?
un sistema di filo verde forse?(Verde perché sarebbe eval per rendere gli utenti si preoccupano per la sicurezza dei thread)

anche se un utente utilizza un import module dichiarazione per caricare un modulo da anche la libreria di default che non viene utilizzato nel resto della classe. ciò potrebbe causare problemi con l'applicazione bloccata da Py2exe, Py2app o Freeze? cosa succede se chiamano un modale lato esterno della libreria standard? sarebbe sufficiente che il modale sia presente nella stessa directory dell'eseguibile congelato?

Mi piacerebbe ottenere queste risposte senza creare una nuova domanda, ma lo farò se devo.

+0

Eval è praticamente impossibile da rendere completamente sicuro imo (ma che non essendo la mia principale area di competenza potrei parlare fuori dal mio culo). Perché non seguire lo sviluppo di un'API con una struttura plug-in per questo, se l'ambito di sicurezza/integrazione e funzionalità è un problema? –

+0

Ehi, almeno non è 'exec'. – nmichaels

+0

Per lo meno, riconosci che questo è uno di quei casi veramente rari in cui un gotta-catch-'em-tutti 'tranne: 'ha un senso e lo applica. Non è necessario arrestare l'intera app perché un utente relativamente nuovo di Python ha perso uno spazio. +1 e preferiti, non vedo l'ora di incorporare un REPL Python in una mia app. – delnan

risposta

5

Risposta facile: no.

È possibile vietare determinate parole chiave (import) e operazioni e accedere a determinate strutture dati, ma in definitiva si sta dando ai vostri utenti un po 'di energia. Dato che questo è per un rich client che viene eseguito sul computer dell'utente, un utente malintenzionato può bloccarsi o persino distruggere l'intera app se ne ha veramente voglia. Ma è il loro caso a schiantarsi. Documentalo bene e racconta alla gente cosa non toccare.

Detto questo, ho fatto questo genere di cose per le applicazioni web che eseguono l'input dell'utente e sì, eval chiamata in questo modo:

eval(code, {"__builtins__":None}, {safe_functions}) 

dove safe_functions è un dizionario contenente {"name": func} tipo paia di funzioni che si desidera i tuoi utenti per poter accedere. Se c'è qualche struttura dati essenziali che sei positivi gli utenti non saranno mai voglia di colpire a, solo pop fuori globals prima di passarli in.

Per inciso, Guido ha affrontato la questione sul suo blog qualche tempo fa. Vedrò se riesco a trovarlo.

Modifica:found.

+0

"Risposta facile: non farlo." -HA! vero, comunque era mia intenzione nel creare questa app per 1) imparare molto su python 2) creare un'applicazione che possa davvero essere utilizzata in modo efficiente e potente. Sono consapevole del fatto che impedire completamente all'utente di rompere qualcosa è impossibile a meno di non consentire loro di eseguire il codice. ma sicuramente è possibile interrompere l'arresto anomalo dell'app se il codice genera un errore che non si aspettavano in circostanze che non si aspettavano. o interrompere l'esecuzione del loro codice se è sospeso perché qualcosa è andato storto. – Ryex

+0

Intendevo non limitarlo. L'aggiunta di funzionalità di scripting è ottima per gli utenti esperti, ma l'avvertenza che possono rompere roba praticamente si applica universalmente. – nmichaels

+1

Puoi invece incorporare qualcosa come PyV8 (http://code.google.com/p/pyv8/), in modo da ottenere comunque un linguaggio di programmazione completo, ma dovresti fornire le tue statistiche globali e aggiungere una dipendenza aggiuntiva . –

1

Breve Risposta: No

Altri Related posts:

Non è facile creare una rete di sicurezza. I dettagli troppi e hack intelligenti sono in giro:

dagli obiettivi di progettazione:

Sembra che si sta tentando di costruire un sistema estendibile, fornendo all'utente di modificare un sacco di comportamento e logica.

L'opzione più semplice è chiedere loro di scrivere uno script che è possibile valutare (valutazione) durante l'esecuzione del programma.

Come sempre, un buon disegno descrive, ambiti la flessibilità e fornisce il meccanismo di scripting attraverso vari schemi progettuali che vanno dalla configurazione, plugin per capacità di scripting ecc le API di scripting se ben definita in grado di fornire estensibilità più significativo. È anche più sicuro.

+0

Non posso essere completamente d'accordo o in disaccordo con l'ultima parte. Un'applicazione che mi permetta di scrivere script mi ​​aiuterà a essere molto più produttivo (oh, tutti quelli X dovrebbero essere Y ... beh, scriverò un ciclo che lo risolve). È una soluzione economica per aiutare gli utenti avanzati. Ma ovviamente la configurazione "reale" e i plugin sono molto convenienti e accessibili anche a più utenti. – delnan

+0

@delnan: sono completamente d'accordo con te. Ma per la maggior parte degli utenti, è ancora più utile fornire estensibilità tramite plugin, API di scripting ecc.Il lavoro che farebbe un utente avanzato sarà molto creativo, ma una lavagna vuota di solito non funziona bene con la maggior parte degli utenti. – pyfunc

0

Suggerirei di fornire una sorta di API plug-in e consentire agli utenti di fornire plug-in sotto forma di file di testo. È quindi possibile importarli come moduli nel proprio spazio dei nomi, rilevando errori di sintassi nel processo e richiamare le varie funzioni definite nel modulo plug-in, verificando nuovamente la presenza di errori. Puoi fornire un modulo API che definisce le funzioni/classi dal tuo programma a cui il modulo plug-in ha accesso. Ciò ti dà la libertà di apportare modifiche all'architettura della tua applicazione senza rompere i plug-in, poiché puoi semplicemente adattare il modulo API per esporre le funzionalità allo stesso modo.

0

Se si ha la possibilità di passare a Tkinter, è possibile utilizzare l'interprete tcl in dotazione per elaborare lo script. Del resto è possibile farlo con un'app wxpython se non si avvia il ciclo di eventi tk; basta usare l'interprete tcl senza creare finestre.

Poiché l'interprete tcl è una cosa separata, è quasi impossibile arrestare in modo anomalo l'interprete python se si presta attenzione a quali comandi si espongono a tcl. Inoltre, tcl rende la creazione di DSL molto semplice.

Python: l'unico linguaggio di scripting con un motore di scripting incorporato :-).