python 解决os.popen 超时问题

Python 使用函数 os.popen 会出现过长时间等待导致阻塞问题。

python 解决os.popen 超时问题

解决方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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()

循环

忙等 子进程结束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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模块 同时可设置子进程的超时时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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)

1
2
3
4
5
6
7
8
9
10
Thread started
Process started
Process finished
Thread finished
0
Thread started
Process started
Terminating process
Thread finished
-15

如果数unix 系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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

本文网址: https://pylist.com/topic/104.html 转摘请注明来源

Suggested Topics

python编程中常用的12种基础知识总结

python编程中常用的12种基础知识总结:正则表达式替换,遍历目录方法,列表按列排序、去重,字典排序,字典、列表、字符串互转,时间对象操作,命令行参数解析(getopt),print 格式化输出,进制转换,Python调用系统命令或者脚本,Python 读写文件。...

python 标准库读写CSV 文件

CSV 是(Comma Separated Values 逗号分隔值)的英文缩写,通常都是纯文本文件。这里介绍使用python 标准库读写csv 文件的方法。...

Leave a Comment