2012-03-21 39 views
8

假設您正在處理一些您不能信任的代碼片段,有沒有辦法在不失去腳本控制的情況下安全地運行它?如何安全運行不可靠的代碼?

一個例子可能是一個函數,它只能在某些時間運行,可能會隨機/壯觀地失敗,您如何才能重試,直到它運行?我嘗試了一些使用線程模塊的黑客攻擊,但是很難整齊地殺死一個掛起的線程。

#!/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

代碼崩潰有多驚人?在你自己的代碼中使用相同的python解釋器運行它甚至是安全的嗎?如果它使用了破損的c擴展(或誤用了未破壞的擴展),或者可能修改了python全局變量,那麼您可能必須在子流程中完全不同的python解釋器中運行它。 – 2012-03-21 11:18:58

回答

5

爲了避免異常,使用try/except(但我想你知道這一點)。

爲了避免掛起代碼(無限循環),我知道的唯一方法是在另一個進程中運行代碼。這個子進程可以從父進程中終止,以防止它很快終止。

爲了避免討厭的代碼(做不該做的事),看看http://pypi.python.org/pypi/RestrictedPython

+3

還有PySandbox - https://github.com/haypo/pysandbox/ – Darb 2012-03-21 17:03:30

4

在你真實的情況下應用程序可以切換到多處理?因爲看起來你所要求的可以用multiprocessing + threading.Timer + try/except完成。

在此請看:

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) 

,在一個(幸運)的情況下給我:

Running 
Empty 
None 
Running 
it worked!! 

在你有4出5機會得到一個錯誤的代碼示例,所以你也可能會產生一個泳池或其他東西來提高你獲得正確結果的機會。

相關問題