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

Asked
Viewd3016

1

我有一个执行某些exe的IronPython脚本。如果它的运行时间超过一定时间,我想停止当前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 个答案

1

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

0

我认为您可以在子流程模块中使用Popen.poll做您想要的事情。(os.popen在2.6中已弃用)

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

  • IronPython不支持

    子进程

    Victor HurdugaciNovember 08, 2009 12:59
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 ]
 
  • IronPython不支持

    子进程。会尝试调整您的代码,看看是否可以解决我的问题

    Victor HurdugaciNovember 08, 2009 12:59
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。

1

由于它在IronPython中,因此我假设它在Windows上运行,因此进程管理可能与我从UNIX了解到的有所不同。

从代码的外观上,您想要做的是:“阅读进程的标准输出,如果运行时间太长,则将其杀死”。为了正确执行此操作,您需要对标准输出进行非阻塞读取,需要从中读取进程输出的临时文件或两个执行线程。

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

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

相关标准库模块:

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