2010-10-14 12 views
7

Estoy haciendo una aplicación wxpython que voy a compilar con la utilidad de congelación para crear un ejecutable para múltiples plataformas.Python - Creando un sistema de "scripting"

el programa será un editer mapa para un motor de juego basado en baldosas

en esta aplicación que quiero para proporcionar un sistema de scripting para que los usuarios avanzados pueden modificar el comportamiento del programa, tales como la modificación de los datos del proyecto, la exportación el proyecto a un formato diferente ect.

Quiero que el sistema funcione así.

el usuario colocará la secuencia de comandos python que desea ejecutar en un cuadro de texto con estilo y luego presiona un botón para ejecutar la secuencia de comandos.

Estoy bien con esto hasta ahora, eso es todo realmente simple. obtener el script desde el cuadro de texto como una cadena de compilar en un objeto de bacalao con la compilación función incorporada() y luego ejecutar el script con un DECLARACIÓN ejecutivo

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

la cosa es que yo quiero para asegurarse de que esta característica no puede causar ningún error o error
decir si hay una declaración de importación en el script. ¿Esto causará algún problema teniendo en cuenta que el código ha sido compilado con algo como py2exe o py2app?
¿Cómo me aseguro de que el usuario no pueda romper una parte crítica del programa como modificar parte de la GUI mientras le permite modificar los datos del proyecto (los datos se guardan en propiedades globales en su propio módulo)? Creo que esto significaría modificar el dict global que se pasa a la función eval.
cómo me aseguro de que esta evaluación no pueda hacer que el programa se bloquee debido a un bucle largo o infinito? ¿cómo me aseguro de que un error generado dentro del código del usuario no pueda bloquear toda la aplicación?

básicamente, ¿cómo evitar todos los problemas que pueden surgir al permitir que el usuario ejecute su propio código?

EDIT: En cuanto a las respuestas dadas

no me siento como cualquiera de las respuestas hasta ahora realmente han respondido a mis preguntas sí lo han sido en parte respondió pero no completamente. Soy consciente de que es imposible detener por completo el código inseguro. las personas son demasiado inteligentes para que un hombre (o incluso un teem) piense en todas las formas de evitar un sistema de seguridad y prevenirlas.

de hecho, realmente no me importa si lo hacen. Estoy más preocupado porque alguien involuntariamente rompió algo que no sabían. si alguien realmente quisiera, podría destrozar la aplicación con la funcionalidad de scripting, pero no podría importarme menos. será su instancia y todos los problemas que creen desaparecerán cuando reinicien la aplicación a menos que se hayan metido con los archivos en la HD. Quiero evitar los problemas que surgen cuando el usuario toma una dosis estúpida.
cosas como IOError, SystaxErrors, InfiniteLoopErrors ect.

ahora se ha respondido la parte sobre el alcance. Ahora entiendo cómo definir qué funciones y variables globales se puede acceder desde la función eval , pero ¿hay alguna forma de asegurarse de que la ejecución de su código se puede detener si tarda demasiado?
¿quizás un sistema de hilo verde?(Verde, ya que sería eval para hacer que los usuarios se preocupan por la seguridad de rosca)

también si un usuario utiliza una instrucción import module para cargar un módulo incluso de la biblioteca por defecto que no se utiliza en el resto de la clase. ¿Podría esto causar problemas con la aplicación congelada por Py2exe, Py2app o Freeze? ¿y si llaman a un lado modal de la biblioteca estándar? ¿Sería suficiente que el modal esté presente en el mismo directorio que el ejecutable congelado?

Me gustaría obtener estas respuestas sin crear una nueva pregunta, pero lo haré si es necesario.

+0

Eval es prácticamente imposible de hacer totalmente seguro (pero esa no es mi principal área de especialización, podría estar hablando de mi trasero). ¿Por qué no ir por el camino de desarrollar una API con una estructura de complemento para esto, si el alcance de seguridad/integración y funcionalidades es una preocupación? –

+0

Oye, al menos no es 'ejecutivo'. – nmichaels

+0

Como mínimo, reconozca que este es uno de esos casos muy, muy raros en los que un getta-catch-em-all 'excepto:' tiene sentido y lo aplica. No es necesario bloquear toda la aplicación porque un usuario relativamente nuevo en python perdió un espacio. +1 y favorito, espero incorporar Python REPL en una aplicación mía también. – delnan

Respuesta

5

Respuesta fácil: no lo hagas.

Puede prohibir ciertas palabras clave (import) y operaciones, y acceder a ciertas estructuras de datos, pero en última instancia le está dando a sus usuarios de energía bastante poder. Dado que esto es para un cliente rico que se ejecuta en la máquina del usuario, un usuario malintencionado puede bloquear o incluso destruir toda la aplicación si realmente lo desea. Pero es su instancia para bloquearse. Documentarlo bien y decirle a la gente lo que no debe tocar.

Dicho esto, he hecho este tipo de cosas para aplicaciones web que se ejecutan entrada del usuario y sí, eval llamada como ésta:

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

donde safe_functions es un diccionario que contiene pares {"name": func} tipo de funciones que desee tus usuarios para poder acceder. Si hay algún tipo de estructura de datos esenciales que eres positivos sus usuarios nunca van a querer meter en, al hacerlo salir de globals antes de pasarlos en.

Por cierto, Guido abordó esta cuestión en su blog hace un tiempo. Veré si puedo encontrarlo.

Editar:found.

+0

"Respuesta fácil: no". -¡DECIR AH! cierto, sin embargo, fue mi intención al crear esta aplicación: 1) aprender mucho sobre python 2) crear una aplicación que realmente se pueda usar de manera eficiente y poderosa. Soy consciente de que impedir completamente que el usuario rompa algo es imposible, salvo que no les permita ejecutar código. pero seguramente es posible evitar que la aplicación se cuelgue si el código genera un error que no esperaban en circunstancias que no anticiparon. o detener la ejecución de su código si se cuelga porque algo salió mal. – Ryex

+0

Quise decir que no lo restrinja. Agregar funcionalidad de scripting es genial para los usuarios avanzados, pero la advertencia de que pueden romper cosas es prácticamente universal. – nmichaels

+1

En su lugar, podría incorporar algo como PyV8 (http://code.google.com/p/pyv8/), de modo que aún obtendría un lenguaje de programación completo, pero tendría que proporcionar sus propios valores globales y agregar una dependencia adicional. . –

1

respuesta corta: No se

Otras entradas relacionadas:

No es fácil crear una red de seguridad. Los detalles demasiados y hacks inteligentes son en torno a:

En sus objetivos de diseño:

Parece que está tratando de construir un sistema extensible, proporcionando al usuario modificar una gran cantidad de comportamiento y lógica.

La opción más fácil es pedirles que escriban un script que puede evaluar (eval) durante la ejecución del programa.

Sin embargo, un buen diseño describe la flexibilidad y proporciona un mecanismo de scripting a través de diversos esquemas de diseño que van desde la configuración, el complemento a las funciones de scripting, etc. Las API aptas si bien definidas pueden proporcionar una extensibilidad más significativa. También es más seguro.

+0

No puedo estar totalmente de acuerdo o en desacuerdo con la última parte. Una aplicación que me permita crear un script me ayudará a ser mucho más productivo (oh, todas esas X deberían ser Y ... bueno, escribiré un ciclo que lo corrija). Es una solución económica para ayudar a los usuarios avanzados. Pero, por supuesto, la configuración y los complementos "reales" son muy prácticos y también accesibles para más usuarios. – delnan

+0

@delnan: estoy completamente de acuerdo con usted. Pero para la mayoría de los usuarios, es aún más útil proporcionar extensibilidad a través de complementos, scripting API, etc.El trabajo que haría un usuario avanzado sería muy creativo, pero una lista en blanco generalmente no funciona bien con la mayoría de los usuarios. – pyfunc

0

Sugiero proporcionar algún tipo de API de complemento y permitir a los usuarios proporcionar complementos en forma de archivos de texto. A continuación, puede importarlos como módulos en su propio espacio de nombres, capturar errores de sintaxis en el proceso y llamar a las diversas funciones definidas en el módulo de plug-in, una vez más buscando errores. Puede proporcionar un módulo de API que defina las funciones/clases de su programa a las que tiene acceso el módulo de complemento. Eso le da la libertad de realizar cambios en la arquitectura de la aplicación sin interrumpir los complementos, ya que solo puede adaptar el módulo API para exponer la funcionalidad de la misma manera.

0

Si tiene la opción de cambiar a Tkinter puede usar el intérprete tcl incluido para procesar su secuencia de comandos. Para el caso, probablemente puedas hacer eso con una aplicación wxpython si no comienzas el ciclo de evento tk; solo use el intérprete tcl sin crear ninguna ventana.

Dado que el intérprete tcl es una cosa separada, debería ser casi imposible bloquear el intérprete python si tiene cuidado con los comandos que expone a tcl. Además, tcl hace que crear DSL sea muy fácil.

Python: el único lenguaje de scripts con un motor de scripting incorporado :-).