我在网上搜索并学习了其他实现方法 现在我发现了问题。我的执行时间总是不止于此 如果我在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
答案 0 :(得分:3)
你不应该只是为了让它在5秒内超时而产生一个新线程,然后使用它的isAlive
状态作为忙碌等待的中断条件。你不需要额外的线程,你可以在第一个线程中弄乱时间。
不应该尽可能频繁地轮询线程,而是应该使用延迟(time.sleep
)来让处理器做一些真正的工作。
你应该知道,如果你的进程产生大量输出,如果你在进程执行时没有读取它会阻塞它,并让它填满管道的缓冲区。
答案 1 :(得分: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)
答案 2 :(得分: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 < 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"])