2012-03-21 7 views
8

Supongamos que está trabajando con un pedazo de código que no puede confiar, ¿hay alguna forma de ejecutarlo de manera segura sin perder el control de su script?¿Cómo ejecutar de forma segura una pieza de código no confiable?

Un ejemplo podría ser una función que solo funciona algunas veces y puede fallar al azar/espectacularmente, ¿cómo podría volver a intentarlo hasta que funcione? Intenté algunas intrusiones con el uso del módulo de subprocesamiento, pero tuve problemas para eliminar perfectamente un hilo colgado.

#!/usr/bin/env python 

import os 
import sys 
import random 

def unreliable_code(): 

    def ok(): 
    return "it worked!!" 

    def fail(): 
    return "it didn't work" 

    def crash(): 
    1/0 

    def hang(): 
    while True: 
     pass 

    def bye(): 
    os._exit(0) 

    return random.choice([ok, fail, crash, hang, bye])() 


result = None 
while result != "it worked!!": 
    # ??? 
+5

¿Qué tan espectacularmente se puede bloquear el código? ¿Es incluso seguro ejecutarlo en el mismo intérprete de Python que tu propio código? Si usa extensiones c rotas (o usa mal las que no están rotas), o potencialmente modifica las globales de python, puede que tenga que ejecutarlo en un intérprete de Python completamente diferente en un subproceso. –

Respuesta

5

Para estar seguro contra las excepciones, utilice try/except (pero supongo que ya lo sabe).

Para estar seguro contra el código colgante (bucle infinito) la única forma que conozco es ejecutar el código en otro proceso. Este proceso secundario lo puede eliminar del proceso padre en caso de que no finalice lo suficientemente pronto.

Para estar seguro contra el código desagradable (hacer cosas que no debe hacer), eche un vistazo a http://pypi.python.org/pypi/RestrictedPython.

+3

También hay PySandbox - https://github.com/haypo/pysandbox/ – Darb

4

En su caso real, ¿puede cambiar al multiprocesamiento? Debido a que parece que lo que está preguntando se puede hacer con multiprocessing + threading.Timer + try/except.

Tome un vistazo a esto:

class SafeProcess(Process): 
    def __init__(self, queue, *args, **kwargs): 
     self.queue = queue 
     super().__init__(*args, **kwargs) 
    def run(self): 
     print('Running') 
     try: 
      result = self._target(*self._args, **self._kwargs) 
      self.queue.put_nowait(result) 
     except: 
      print('Exception') 

result = None 
while result != 'it worked!!': 
    q = Queue() 
    p = SafeProcess(q, target=unreliable_code) 
    p.start() 
    t = Timer(1, p.terminate) # in case it should hang 
    t.start() 
    p.join() 
    t.cancel() 
    try: 
     result = q.get_nowait() 
    except queues.Empty: 
     print('Empty') 
    print(result) 

que en un caso (suerte) me dio:

Running 
Empty 
None 
Running 
it worked!! 

En los ejemplos de código que tiene 4 de cada 5 oportunidades de conseguir un error, por lo que también podría generar un grupo o algo para mejorar sus posibilidades de tener un resultado correcto.

Cuestiones relacionadas