2

私はインターネットで検索し、問題を実装する他の方法を学びました。subprocess.Popen に stdout=subprocess.PIPE と書くと必ず実行時間がタイムアウト以上になってしまいます。私がそれを削除している場合、通常の実行時間がかかっています

import subprocess, datetime, os, time, signal
//setting time for timeout
timeout=3
start = datetime.datetime.now()
process = subprocess.Popen(["python", "/home/bourne/untitled.py"],shell=False, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
while process.poll() is None:
        time.sleep(0.1)
        now = datetime.datetime.now()
        if (now - start).seconds > timeout:
            os.kill(process.pid, signal.SIGKILL)
            os.waitpid(-1, os.WNOHANG)
            print "error"       
            print (now - start).seconds
            break
        print (now - start).seconds
4

3 に答える 3

3

5 秒でタイムアウトするためだけに新しいスレッドを生成し、そのisAliveステータスをビジー待機のブレーク条件として使用しないでください。そのために余分なスレッドは必要ありません。最初のスレッドで時間を混乱させることができます。

できるだけ頻繁にスレッドをポーリングする代わりに、遅延 ( time.sleep) を使用して、プロセッサが実際の作業を行えるようにする必要があります。

また、プロセスが大量の出力を生成している場合、プロセスの実行中にそれを読み取らないとブロックされ、パイプのバッファーがいっぱいになることを知っておく必要があります。

于 2012-05-24T09:01:20.697 に答える
0

スレッドは Python VM で処理できますが、処理はできません。したがって、OS api を使用して、(Linux の場合) 次のようなプロセス/サブプロセスを強制終了する必要があります。

os.system("kill -9 %s"%(proc.pid))

そして、タイミングのためにスレッドを使用するのは悪い考えです。どうですか:

start_t = time.time()
TIME_END, TIME_SLEEP = 5, 1
while time.time() - start_t < TIME_END:
    if proc.poll():
        break
    time.sleep(TIME_SLEEP)
于 2012-05-24T09:14:02.563 に答える
0
I have successfully solved the problem. the solution is 

import subprocess, signal, os, threading, errno
from contextlib import contextmanager

class TimeoutThread(object):
    def __init__(self, seconds):
        self.seconds = seconds
        self.cond = threading.Condition()
        self.cancelled = False
        self.thread = threading.Thread(target=self._wait)

    def run(self):
        """Begin the timeout."""
        self.thread.start()

    def _wait(self):
        with self.cond:
            self.cond.wait(self.seconds)

            if not self.cancelled:
                self.timed_out()

    def cancel(self):
        """Cancel the timeout, if it hasn't yet occured."""
        with self.cond:
            self.cancelled = True
            self.cond.notify()
        self.thread.join()

    def timed_out(self):
        """The timeout has expired."""
        raise NotImplementedError

class KillProcessThread(TimeoutThread):
    def __init__(self, seconds, pid):
        super(KillProcessThread, self).__init__(seconds)
        self.pid = pid

    def timed_out(self):
        try:
            os.kill(self.pid, signal.SIGKILL) // this is for linux you need to change it for windows
        except OSError,e:
            # If the process is already gone, ignore the error.
            if e.errno not in (errno.EPERM, errno. ESRCH):
                raise e

@contextmanager
def processTimeout(seconds, pid):
    timeout = KillProcessThread(seconds, pid)
    timeout.run()
    try:
        yield
    finally:
        timeout.cancel()


def example(cmd):
    proc = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
    //setting the timeout to be 1 sec
    with processTimeout(1, proc.pid):
        stdout,stderr=proc.communicate()       

    resultcode = proc.wait()
    if resultcode &lt; 0:
        #print "error: %i" % resultcode
        return resultcode,0
    else:
        return stdout,stderr





//This is used to create new subprocess and it will return output as well as error
output,err=example(["python",filepath,"5"])
于 2012-07-21T06:43:20.583 に答える