python 解决os.popen 超时问题

zeroman 1528 2

os.popen 会出现过长时间等待导致阻塞问题, 解决方法如下:

def TIMEOUT_COMMAND(command, timeout):
    """call shell-command and either return its output or kill it
    if it doesn't normally exit within timeout seconds and return None"""
    import subprocess, datetime, os, time, signal
    cmd = command.split(" ")
    start = datetime.datetime.now()
    process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    while process.poll() is None:
        time.sleep(0.2)
        now = datetime.datetime.now()
        if (now - start).seconds> timeout:
            os.kill(process.pid, signal.SIGKILL)
            os.waitpid(-1, os.WNOHANG)
            return None
    return process.stdout.readlines()

循环 忙等 子进程结束

import subprocess
import os
import time
tt = '555'
cmd = "python /home/100003/python/mypython/sub2.py "+" 333"+" 444 "+tt
print time.time()
sub2 = subprocess.Popen(cmd, shell=True)
while 1:
    ret1 = subprocess.Popen.poll(sub2)
    if ret1 == 0:
        print sub2.pid,'end'
        break
    elif ret1 is None:
        print  'running'
        time.sleep(1)
    else:
        print sub2.pid,'term'
        break
print time.time()

子进程结束 立即返回 使用select模块 同时可设置子进程的超时时间

import subprocess
import select
import time
import signal
import os

tt = '555'
cmd = "python /home/100003/python/mypython/sub2.py "+" 333"+" 444 "+tt
timeout = 3
pro = subprocess.Popen(cmd, stdout=subprocess.PIPE,shell = True)
print time.time()
while 1:
    while_begin = time.time()
    print 'timeout',timeout
    fs = select.select([pro.stdout], [], [], timeout)
    if pro.stdout in fs[0]:
        tmp = pro.stdout.read()
        print 'read', tmp
        if not tmp:
            print 'end'
            print time.time()
            break
    else:
        print 'outoftime'
        print os.kill(pro.pid, signal.SIGKILL),
        break
    timeout = timeout - (time.time() - while_begin)

该主题到 2015-07-02 16:26:08 共 2 条回复
z
zeroman #
import subprocess, threading

class Command(object):
    def __init__(self, cmd):
        self.cmd = cmd
        self.process = None

    def run(self, timeout):
        def target():
            print 'Thread started'
            self.process = subprocess.Popen(self.cmd, shell=True)
            self.process.communicate()
            print 'Thread finished'

        thread = threading.Thread(target=target)
        thread.start()

        thread.join(timeout)
        if thread.is_alive():
            print 'Terminating process'
            self.process.terminate()
            thread.join()
        print self.process.returncode

command = Command("echo 'Process started'; sleep 2; echo 'Process finished'")
command.run(timeout=3)
command.run(timeout=1)
Thread started
Process started
Process finished
Thread finished
0
Thread started
Process started
Terminating process
Thread finished
-15
z
zeroman #

http://stackoverflow.com/questions/1191374/subprocess-with-timeout 1

If you're on Unix,

import signal

proc = subprocess.Popen(
    cmd,
    stderr=subprocess.STDOUT,  # merge stdout and stderr
    stdout=subprocess.PIPE,
    shell=True)

  ...
class Alarm(Exception):
    pass

def alarm_handler(signum, frame):
    raise Alarm

signal.signal(signal.SIGALRM, alarm_handler)
signal.alarm(5*60)  # 5 minutes
try:
    stdoutdata, stderrdata = proc.communicate()
    signal.alarm(0)  # reset the alarm
except Alarm:
    print "Oops, taking too long!"
    # whatever else
登录发表评论

桂公网安备 45122402000014号