Python:在最长时间后停止执行

时间:2009-11-08 12:50:48

标签: ironpython

我有一个执行一些exes的IronPython脚本。如果当前的exe超过一定的时间,我想停止执行当前的exe。我怎么能这样做?

当前功能:

def execute(programName):
    t0 = time.time()
    #should stop the execution of "programName"
    #if execution exceeds limit
    p = os.popen(programName,"r")
    result = p.readline()
    p.close()
    execTime = time.time() - t0
    return result, execTime

5 个答案:

答案 0 :(得分:1)

这段代码适用于我使用python。我不确定它在IronPython上的表现如何,希望无论如何都会有所帮助。

"""
Monitors a set of processes execution, and termination
"""

import subprocess
from threading import Thread
import time

class ProcessMonitor( Thread ):
    def __init__(self):
        Thread.__init__(self)
        self.processList = {}
        self.running = True

    def monitor( self, pClass, timeout ):
        self.processList[ pClass ] = (time.time(),0,timeout)

    def stop(self):
        running = false

    def run(self):
        print time.time()  # just for debugging!!
        while self.running:
            # sleep for a second
            time.sleep(10)
            # go over all processes and update the time
            for pClass in self.processList:
                currentTime = time.time()
                # if the process didn't terminate yet
                if pClass.poll() == None:
                    # check if needs to be terminated!
                    (time_,overall,timeout)=self.processList[pClass]
                    overall = overall + (currentTime-time_)
                    print "%f seconds passed from running of process %d"%(overall,pClass.pid)
                    if overall > timeout:
                        pClass.kill()
                        del self.processList[ pClass]
                    else:
                        self.processList[pClass] = (currentTime,overall,timeout)
                else:
                    del self.processList[ pClass ]

答案 1 :(得分:1)

由于它在IronPython中,我认为它在Windows上运行,因此进程管理可能与我从unix中所知的不同。

从您的代码来看,您要做的是:“读取流程的标准输出,如果运行时间过长就将其删除”。要正确执行此操作,您需要标准输出上的非阻塞读取,读取进程输出的临时文件或两个执行线程。

一个线程将读取子进程输出。

另一个线程将定期轮询进程以检查它是否终止,如果它在一段时间后没有终止,则将其终止。如果你不想轮询,你需要一个额外的线程:一个到子进程的wait(),另一个在一段时间后杀掉它。

相关标准库模块:

  • subprocess:使用此代替popen,在各方面都更好。
  • sched:在单个线程中实现定期轮询和查杀的基本调度程序。
  • threading:高级线程库。特别是threading.Timer对于构建无轮询的解决方案至关重要。

答案 2 :(得分:1)

如果您不需要与CPython兼容的代码(听起来不像那样),您可以使用.NET facilities进行流程管理,例如System.Diagnostics.Process类。它可能比使用os.popen更简单。

答案 3 :(得分:1)

这是我如何做的...它确实使用了子进程,所以你需要调整它以使用popen。

class KillerThread(threading.Thread):
  def __init__(self, pid, timeout, event ):
    threading.Thread.__init__(self)
    self.pid = pid
    self.timeout = timeout
    self.event = event
    self.setDaemon(True)
  def run(self):
    self.event.wait(self.timeout)
    if not self.event.isSet() :
      try:
        os.kill( self.pid, signal.SIGKILL )
      except OSError, e:
        #This is raised if the process has already completed
        pass

def runTimed(dt, args, kwargs ):
  event = threading.Event()
  proc = subprocess.Popen(args, **kwargs )
  killer = KillerThread(proc.pid, dt, event)
  killer.start()

  (stdout, stderr) = proc.communicate()
  event.set()
  return (stdout,stderr, proc.returncode)

#EXAMPLE USAGE - lets it run for at most 3 seconds
(stdout, stderr, returncode) = \
runTimed(3, \
    ["path/to/my/executable", "arg1" ] , \
    {'stdout':subprocess.PIPE, 'stderr':subprocess.PIPE} ) 

如果使用stderr,stdout,则可以避免需要额外的线程 直接而不是使用通信,您只需要小心在这些句柄上使用非阻塞IO。

答案 4 :(得分:0)

我认为您可以在子进程模块中使用Popen.poll来执行您想要的操作。 (os.popen在2.6中弃用)

http://docs.python.org/library/subprocess.html