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 转摘请注明来源