简体   繁体   English

如何安全地运行不可靠的代码?

[英]How to safely run unreliable piece of code?

Suppose you are working with some bodgy piece of code which you can't trust, is there a way to run it safely without losing control of your script? 假设你正在处理一些你不能相信的笨重的代码,有没有办法安全地运行它而不会失去对脚本的控制?

An example might be a function which only works some of the time and might fail randomly/spectacularly, how could you retry until it works? 一个例子可能是一个只在某些时候起作用的函数,并且可能会随机/壮观地失败,你怎么能重试直到它工作? I tried some hacking with using threading module but had trouble to kill a hung thread neatly. 我尝试使用线程模块进行一些黑客攻击,但很难整齐地杀死一个挂起的线程。

#!/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!!":
  # ???

To be safe against exceptions, use try/except (but I guess you know that). 为了安全抵御异常,请使用try / except(但我想你知道)。

To be safe against hanging code (endless loop) the only way I know is running the code in another process. 为了安全地防止挂起代码(无限循环),我知道的唯一方法是在另一个进程中运行代码。 This child process you can kill from the father process in case it does not terminate soon enough. 这个子进程可以从父进程中终止,以防它不能很快终止。

To be safe against nasty code (doing things it shall not do), have a look at http://pypi.python.org/pypi/RestrictedPython . 为了安全抵御令人讨厌的代码(不应该做的事情),请查看http://pypi.python.org/pypi/RestrictedPython

您可以尝试在沙箱中运行它。

In your real case application can you switch to multiprocessing? 在您的实际情况下,您可以切换到多处理应用程序吗? Becasue it seems that what you're asking could be done with multiprocessing + threading.Timer + try/except . 看来你的问题似乎可以通过multiprocessing + threading.Timer来完成threading.Timer + try/except

Take a look at this: 看看这个:

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)

That in one (lucky) case gave me: 在一个(幸运的)案例中,我给了我:

Running
Empty
None
Running
it worked!!

In your code samples you have 4 out of 5 chances to get an error, so you might also spawn a pool or something to improve your chances of having a correct result. 在您的代码示例中,您有五分之四的机会获得错误,因此您可能还会产生一个池或某些东西,以提高您获得正确结果的机会。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM